容斥原理与gcd的问题
gcd个数的处理(i,j无限制)
P2398 GCD SUM
i为1-n,j为1-m,求gcd为k的个数
代码
#include <bits/stdc++.h> using namespace std; #define int long long const int M=1e5+5; int f[M]; signed main() { int n;cin>>n; for(int i=n;i>=1;i--) { f[i]=(n/i)*(n/i); for(int j=i+i;j<=n;j+=i)f[i]-=f[j]; } //左边多少个数,右边多少个数 int ans=0; for(int i=1;i<=n;i++)ans+=i*f[i]; cout<<ans<<endl; return 0; } //可以求出每一对gcd的数量
(i<j)
CF--841--E
gcd个数处理+贪心
其实也就是在上面的基础上除2的处理
#include <bits/stdc++.h> using namespace std; #define int long long const int M=1e6+5; int a[M]; signed main() { int TT;cin>>TT; while(TT--) { int n,m,ans=0; cin>>n>>m; for(int i=n;i>=2;i--) { int k=i-1;//一次多少边 a[i]=(n/i)*(n/i-1)/2; for(int j=2*i;j<=n;j+=i)a[i]-=a[j]; int w=a[i]/k*k;//多少边 if(w>m)w=m/k*k; m-=w; ans+=w/k*(k+1); } if(m>0)cout<<"-1\n"; else cout<<ans<<endl; } return 0; } //适用容斥进行相减即可
1-n中与n互质的数的个数
可以适用欧拉,也可以适用容斥
欧拉
int phi(int x) { int res = x; for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) { res = res / i * (i - 1); while (x % i == 0) x /= i;//一次性消除全部i } if (x > 1) res = res / x * (x - 1);//有没有遗漏 return res; }
容斥
但如果是1-n中与m互质的个数,就必须适用容斥了
//1-n中与m互质的数的个数 int phi(int n,int m) { vector<int>v; for(int i=2;i*i<=m;i++) if(m%i==0) { v.push_back(i); while(m%i==0)m/=i; } if(m>1)v.push_back(m); int sz=v.size(); int sum=0; for(int i=1;i<(1<<sz);i++) { int cnt=0,tmp=1; for(int j=0;j<sz;j++) if(i>>j&1) { cnt++; tmp*=v[j]; } if(cnt&1)sum+=n/tmp; else sum-=n/tmp; } return n-sum; }
总结
这种求gcd数量的题,大体都可以适用容斥原理
求gcd==x,要用除法
可以先将整天出去x,然后利用欧拉函数进行计算。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】