欧拉函数:给你一个数字p,表示1-p中与p互质的数的数量
求欧拉函数模板
ll phi(ll x){
ll ans=x;
for(int i=2;i*i<=x;i++){
if(x%i==0){
ans=ans*(i-1)/i;
while(x%i==0)x/=i;
}
}
if(x>1)ans=ans*(x-1)/x;
return ans;
}
利用线性筛去求快速求1-n每个数的欧拉函数模板
欧拉函数的一些性质:
当n与m互质时,(n*m)=
(n)*
(m)
m时n*m的最小质因子,如果n是m的倍数时
则, (n*m)=
(n)*m;
根据上面的性质则可以通过线性筛递推出1-n每个数字的欧拉函数
ll d1[N]={0},d2[N],d3[N]={0};
ll phi[N]={0};
void shai(ll n){
int i,j,k=0;
phi[1]=1;
for(i=2;i<=n;i++){
if(d1[i]==0){
d2[++k]=i;
phi[i]=i-1;
}
for(j=1;j<=k&&i*d2[j]<=n;j++){
d1[i*d2[j]]=1;
if(i%d2[j]==0){
phi[i*d2[j]]=phi[i]*d2[j];break;
}else{
phi[i*d2[j]]=phi[i]*phi[d2[j]];
}
}
}
}
题目:
P2568 GCD - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
对于一个gcd(a,b)=1,它等价于gcd(a*p,b*p)=p;
考虑每一个质数p对答案的贡献,求出(a,b)的范围
因该是max(a,b)*p<=n;
那么一个素数p的贡献因该是,小于等于n/p的所有的数字的欧拉函数的和*2(除了1)
通过线性筛处理出1-n所有的欧拉函数,再写一个前缀和数组即可做出本题
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
const ll N = 2e7+10;
ll a[N]={0};
ll b[N]={0};
ll phi[N]={0};
vector<int>v;
void shai(ll n){
int i,j,k=0;
v.push_back(-1);
phi[1]=1;
for(i=2;i<=n;i++){
if(a[i]==0){
v.push_back(i);
phi[i]=i-1;
}
k=v.size();
for(j=1;j<k&&i*v[j]<=n;j++){
// cout<<v[j]<<endl;
a[i*v[j]]=1;
if(i%v[j]==0){
phi[i*v[j]]=phi[i]*v[j];
}else{
phi[i*v[j]]=phi[i]*phi[v[j]];
}
}
}
}
ll phi(ll x){
ll ans=x;
for(int i=2;i*i<=x;i++){
if(x%i==0){
ans=ans*(i-1)/i;
while(x%i==0)x/=i;
}
}
if(x>1)ans=ans*(x-1)/x;
return ans;
}
void solve(){
ll n,i,j,u,ans=0;
cin>>n;
shai(n);
u=v.size();
b[0]=0;
for(i=1;i<=n;i++){
if(i==1){
b[i]=1;
continue;
}
b[i]=b[i-1]+phi[i]*2;
}
for(i=1;i<u;i++){
ans+=b[n/v[i]];
}
cout<<ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
// cin>>t;
t=1;
while(t--){
solve();
}
}