Problem
对于任意正整数 ,试问 中,有多少正数与 互质?
Idea
考虑容斥原理,求互质的个数,可以用总个数 减去不互质的数字的个数。
求与 其不互质的数字,原理上就是求 的 的数量,考虑分解质因数判断。
先预处理 的质因数分解方案,即 。
记 表示 的欧拉函数,则根据容斥原理,有:
总情况数
减去所有单个质因子的情况:
加上所有两项之积:$+\frac n {P_1 P_2}+\frac n {P_1 P_3}+\dots+\frac n {P_2 P_3}+\dots+\frac n {P_{k-1} P_k} $
减去所有三项之积:
以此类推:
直到所有项之积:
#include<bits/stdc++.h>
using namespace std;
int eular(int n) {
int res=n,tot=n;
vector<int> v;
for(int i=2;i*i<=n;++i) {
if(n%i) continue;
res=res*(i-1)/i;
while(n%i==0) n/=i;
}
if(n) res=res*(n-1)/n;
return res;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int TT;
cin>>TT;
while(TT--) {
int n;
cin>>n;
cout<<eular(n)<<'\n';
}
return 0;
}
筛法求欧拉函数
使用埃氏筛辅助算出每个数的质因子,可以快速地 预处理出 中每个数的 。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6+7;
ll el[N];
ll tot_eular(int n) {
for(int i=1;i<=n;++i) el[i]=i;
for(int i=2;i<=n;++i) {
if(el[i]!=i) continue;
for(int j=i;j<=n;j+=i)
el[j]=el[j]*(i-1)/i;
}
ll res=0;
for(int i=1;i<=n;++i) res+=el[i];
//for(int i=1;i<=n;++i) cout<<el[i]<<' ';
return res;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
cout<<tot_eular(n)<<'\n';
return 0;
}