51nod level-5 系列
2017-8-15
题目思路:满足 gcd(x,n)==d 的x的数量即是 最大公约数d的贡献度,
那么 gcd(x,n)==d 的数量 等价于 gcd(x/d,n/d)==1的数量 , 即为欧拉函数
因此,我们枚举n所有的因子i,求一个euler(n/i) 即为gcd==i的数量,
又由于这里 n是1e9范围 , 因子都是成对出现的 因此可以枚举因子到根号n即可
若是两个因子不相等,那么两个因子的贡献度都要加上,相等只需要算一次
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 int n; 7 //int euler[100010]; 8 9 //void init(){ 10 // euler[1]=1; 11 // for(int i=2;i<100000;i++) 12 // euler[i]=i; 13 // for(int i=2;i<100000;i++) 14 // if(euler[i]==i) 15 // for(int j=i;j<100000;j+=i) 16 // euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出 17 //} 18 19 //直接求解欧拉函数 20 int euler(int n){ //返回euler(n) 21 int res=n,a=n; 22 for(int i=2;i*i<=a;i++){ 23 if(a%i==0){ 24 res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出 25 while(a%i==0) a/=i; 26 } 27 } 28 if(a>1) res=res/a*(a-1); 29 return res; 30 } 31 32 33 int main() 34 { 35 36 scanf("%d",&n); 37 LL ans=0; 38 for(int i=1;i*i<=n;i++) 39 { 40 if(n%i) continue; 41 int d=n/i; 42 ans=ans+1LL*euler(d)*i; 43 if(d!=i) ans=ans+1LL*euler(i)*d; 44 } 45 printf("%lld\n",ans); 46 }