博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ACM-ICPC (10/11)
阅读量:6766 次
发布时间:2019-06-26

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

莫比乌斯

今年的多校比赛,莫比乌斯反演的题目经常出现,但是我们队对于这种题可以说是直接放掉,不是因为没学过,多少了解一些,但是也只是皮毛,导致根本就做不出来,其实想一想,其实次数多了,就可以看出原因了,没有过总结,没有过思考,昨天心血来潮,好好的看了一下莫比乌斯反演,有一点感悟!

 

  • 什么是莫比乌斯反演

...

 

可以通过​ 反向推导出

...

 

公式:

 

其中 即为莫比乌斯函数。

 

也可以如下定义:

  •  

  • 分解质因数,无不相同,则

  • 其他为0

性质:积性函数

莫比乌斯(容斥的优化)——我的理解

 

怎么求莫比乌斯函数?

  • 类似于筛素数的方案,O(nlogn),一般足够了。

  • 级别,无法预处理出1~n的莫比乌斯表,利用因式分解,讨论因子的拿法(类似压状),O(sqrt(n))

栗子:

 

 

 

//求莫比乌斯函数 O(nlogn) void getMu() {
   for(int i = 1; i < maxn; i++) { int target = i == 1 ? 1 : 0; int delta = target - mu[i]; mu[i] = delta; for(int j = i + i ; j < maxn; j+=i) mu[j] +=delta; } }

 

// n 的 约数的莫比乌斯函数值map形式返回 O(sqrt(n)) map
moebius(int n) { map
res; vector
primes; //枚举n的质数 for(int i = 2; i*i <= n; i++) { if(n%i==0) { primes.push_back(i); while(n%i==0) n/=i; } } if(n!=1) primes.push_back(n); int m = primes.size(); //不超过n的约数个数 次 for(int i = 0; i < (1<
>j&1) { mu*=-1; d*=primes[j]; } } res[d] = mu; } return res; }

 

例题一:

分析:总共26^n,根据容斥,枚举最短循环节d,减去26^d,根据莫比乌斯函数来容斥优化。注意数据范围极大!

#include 
​ using namespace std; ​ typedef long long ll; // n 的 约数的莫比乌斯函数值map形式返回 O(sqrt(n)) map
moebius(int n) { map
res; vector
primes; //枚举n的质数 for(int i = 2; i*i <= n; i++) { if(n%i==0) { primes.push_back(i); while(n%i==0) n/=i; } } if(n!=1) primes.push_back(n); int m = primes.size(); //不超过n的约数个数 次 for(int i = 0; i < (1<
>j&1) { mu*=-1; d*=primes[j]; } } res[d] = mu; } return res; } const int MOD = 10009; int n; //快速幂取模 a^b % mod; ll pow_mod(ll a,ll b) { if(b==0) return 1%MOD; int temp = pow_mod(a,b>>1); temp = temp*temp%MOD; if(b&1) temp = (ll)temp*a%MOD; return temp;}void solve() { ll res = 0; map
mu = moebius(n); for(auto it = mu.begin(); it != mu.end(); it++) { //printf("%d %d\n",it->first,it->second); res += (ll)it->second*pow_mod(26,n/it->first); res = (res%MOD + MOD) % MOD; } printf("%I64d\n",res);}int main(){ scanf("%d",&n); solve(); return 0;}

 

例题二:

 

分析:

 

注意:(1,3),(3,1)相同。

先考虑不同的情况:

 

即:两个区间内互质的对数,同理:总共 对,减去不符合情况的对数,枚举gcd,就有 * 对,然后用莫比乌斯来容斥。

怎么解决(1,3)(3,1)相同的情况呢?

还是容斥!!!

减去较小区间做一遍上述操作的一半。

#include 
​ using namespace std; ​ const int maxn = 1<<20; int mu[maxn]; //求莫比乌斯函数 void getMu() { for(int i = 1; i < maxn; i++) { int target = i == 1 ? 1 : 0; int delta = target - mu[i]; mu[i] = delta; for(int j = i + i ; j < maxn; j+=i) mu[j] +=delta; } } int main() { getMu(); int T; scanf("%d",&T); for(int z = 1; z <= T; z++) { int a,b,c,d,k; scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k==0) { puts("0"); continue; } b/=k; d/=k; if(b>d) swap(b,d); //b小 long long ans1 = 0; for(int i = 1; i <= b; i++) ans1 += (long long)mu[i]*(b/i)*(d/i); long long ans2 = 0; for(int i = 1; i <= b; i++) ans2 += (long long)mu[i]*(b/i)*(b/i); ans1 -= ans2/2; printf("%I64d\n",ans1); } return 0;}

 

例题三:

题意:给定一个正方体的区间,从坐标(0,0,0)处可以看到多少个整点?

分析:(1,1,1) 能看到,但是(2,2,2)就三点共线挡住了,同理(2,3,4)能看到,但是(4,6,8)就看不到了,可以看出就是 的点,被除以gcd的点挡住了。也就是求 (x,y,z)互质的点对,就是上一题加一维。

值得注意的是区间是[1,n],整个坐标系可以x = 0等,x等于0,相当于一个平面,减一围。

还有3个坐标轴上的点。

#include 
​ using namespace std; ​ const int maxn = 1<<20; int mu[maxn]; //求莫比乌斯函数 void getMu() { for(int i = 1; i < maxn; i++) { int target = i == 1 ? 1 : 0; int delta = target - mu[i]; mu[i] = delta; for(int j = i + i ; j < maxn; j+=i) mu[j] +=delta; } } typedef long long ll; int main() { getMu(); int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); ll ans = 3; for(int i = 1; i <= n; i++) ans+= (ll)mu[i]*(n/i)*(n/i)*(n/i+3); printf("%lld\n",ans); } return 0; }

 

到此,你就已经入门莫比乌斯了~~~

TreeDream

 

转载于:https://www.cnblogs.com/TreeDream/p/7653242.html

你可能感兴趣的文章
分治法理论
查看>>
澄甫先生谓古人练拳分四步功夫
查看>>
第八天
查看>>
C# Lambda表达式
查看>>
Android Studio中多项目共享Library
查看>>
用java的io流,将一个文本框的内容反转
查看>>
python: 不同级别的日志输出到不同文件的日志类
查看>>
[LeetCode] Trapping Rain Water
查看>>
linux下下载redis,并且编译
查看>>
FirstOrDefault()的重载方法
查看>>
SumElemet
查看>>
团队编程
查看>>
ajax轮询session阻塞问题
查看>>
C++三大特性之封装
查看>>
【总结整理】WebGIS学习-thinkGIS(三):关于影像金字塔、瓦片行列号、分辨率resolution...
查看>>
冒泡排序的探究
查看>>
原生网络请求以及AFN网络请求/异步下载
查看>>
h3c 云计算管理平台
查看>>
C#读取网络流,读取网络上的js文件
查看>>
韩星5,6号 一锅双星技巧
查看>>