博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
莫比乌斯反演
阅读量:6958 次
发布时间:2019-06-27

本文共 2410 字,大约阅读时间需要 8 分钟。

 

莫比乌斯反演

当满足以下求和函数: 

可以得到:

F(1)=f(1)                 F(2)=f(1)+f(2)

F(3)=f(1)+ f(3)           F(4)=f(1)+f(2)+f(4)                      F(5)=f(1)+f(5)

推出:

f(1)=F(1)                 f(2)=F(2)-f(1)=F(2)-F(1)

f(3) =F(3)-F(1)           f(4)=F(4) -f(2)- f(1) =F(4)-F(2)

f(5) =F(5)-F(1)

可以反推出求f(x)的式子:

 

  

在上面的公式中有一个函数,它的定义如下:

 

    (1)若,那么

    (2)若均为互异素数,那么

    (3)其它情况下

函数可以通过筛选求出:

 

 

然后是关于莫比乌斯求GCD的原理,当时看了很久感觉并无法满足上面公式,后来才发现还有公式2(╯▽╰)

 

即F[n]等于n的倍数d,f[d]的和,然后可以反演出后面公式

对于GCD(x,y) = k

设f[d]: GCD(x,y) = k  ,即最大公约数为k的(x,y)的对数   

  F[n]: n|GCD(x,y) ,即最大公约数是n的倍数的(x,y)的对数

所以:F{1] = f[1] + .... + f[n]

     F[2] = f[2] + f[4] + ....f[2*i]...

可以发现完全满足上面的公式

而且对于F[n],可以求出F[n] = (a/n)*(b/n)

因此我们可以再利用反演求f[d]

 

void Moblus(){    tot = 0;    memset(is_prime,0,sizeof(is_prime));    mu[1] = 1;    for(int i = 2; i <= maxn; i++)    {        if(!is_prime[i])        {            prime[tot++] = i;            mu[i] = -1;        }        for(int j = 0; j < tot; j++)        {            if(prime[j]*i>maxn)                break;            is_prime[i*prime[j]] = 1;            if(i % prime[j])             //prime[j]不重复            {                mu[i*prime[j]] = -mu[i];            }            else            {                mu[i*prime[j]] = 0;                break;            }        }    }}

  

题:,

 

 

关于优化:

在计算中,我们是枚举1->n计算,每次ans+= mu[i] * (a/i) * (a/i)

我们可以发现,由于是除法计算,所以经常出现a/i = a/(i+1) = .... = a/(i+k)  例如:8/3 = 8/4

所以每次循环我们可以计算出,相等值的长度,然后在用sum保存mu的和,一次循环便能计算出一段数的值

ll gett(int n,int m)        //分块优化  {      ll ret = 0;      int i,last;      if(n > m)          swap(n,m);      for(i = 1,last = 0;i<=n;i=last+1)      {           last = Min(n/(n/i),m/(m/i));      //求为n/i时的最远位置           ret += (ll)(n/i)*(m/i)*(sum[last]-sum[i-1]);      }     return ret;  }

  

 

 

参考文章:

/************************************************分界线*******************************************************/

:求GCD                  /*个人理解

对于求GCD,我们可以看成先求出所有选择的情况,然后减去GCD不为1(即把数分成各个因子的集合)

例:num[2]能被2约去的数,然后减去这些数,我们会发现减去了2,3后,6会被多减,所有需要加上,于是满足了

莫比乌斯函数.大致思路:

C(n,k) - C(gcd只含奇数个质数的个数,k) + C(gcd只含偶数个质数的个数,k),前面的符号就是莫比乌斯函数

一种是求1≤x≤n,1≤y≤m中多少对(x,y)满足gcd(x,y) = 1,  /*比如上面的hdu1695

推出公式:for(i->min(n,m)) ans += mu[i]*(n/i)*(m/i),

完全可以看成在i = 1时求出所有情况,然后2的倍数(即可能gcd = 2的情况),减去3的倍数...加上6的倍数......。

另一种是给你特定的几个数,让你求他们互质的情况(其中k个数互质)。

我们也是先计算出总的情况,而且筛选出,每个这些数中,是i的倍数的个数,用num保存。

因为是在一个集合中,加上num[i] = x,则选出gcd = i的情况:x*(x-1)

②:完全平方数的问题

例如求不是完全平方数的倍数,我们要减去比如4,9,16什么的,刚好和他们根号下的莫比乌斯函数符号相同。

利用这个性质可以很愉快的算出。

/*新手一个,若有错误还请见谅 ,^O^,

/*尽管很弱,真的真的很想参加区域赛!!

 

转载于:https://www.cnblogs.com/Przz/p/5409698.html

你可能感兴趣的文章
[CALayer release]: message sent to deallocated instance iOS内存过度释放问题
查看>>
WPF界面设计技巧(4)—自定义列表项样式
查看>>
git push的时候每次都要输入用户名和密码的问题解决
查看>>
hiho_1138_island_travel
查看>>
love2d教程13--图形界面
查看>>
POJ 1276 Cash Machine
查看>>
C语言中 struct成员变量顺序对内存的占用
查看>>
POJ1291-并查集/dfs
查看>>
移动办公首选!电商热卖轻薄本高低该怎么选?
查看>>
[译] RNN 循环神经网络系列 1:基本 RNN 与 CHAR-RNN
查看>>
Android技能树 — PopupWindow小结
查看>>
如何在create-react-app项目中使用vw实现手淘vw移动端适配布局
查看>>
Wormhole燃烧地址到底有多安全
查看>>
Web探索之旅 | 第三部分第三课:协议
查看>>
20个优秀手机界面扁平化设计,让你一秒看懂扁平化
查看>>
从百度的PPT文化看程序员晋升
查看>>
Python测试登录功能
查看>>
babel插件入门-AST(抽象语法树)
查看>>
ubuntu 16.04下docker的安装
查看>>
web页面渲染(一)
查看>>