容斥原理与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,然后利用欧拉函数进行计算。

posted @   basicecho  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示