51nod1040 最大公约数之和

求$sum_{i=1}^{n}(i,n)$。n<=1e9。

$sum_{i=1}^{n}(i,n)=sum_{d|n}dsum_{i=1}^{n}[(i,n)=d]=sum_{d|n}dsum_{k=1}^{frac{n}{d}}[(k,frac{n}{d})=1]=sum_{d|n}dvarphi(frac{n}{d})=sum_{d|n}frac{nvarphi(d)}{d}$

枚举因子。搞定。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 //#include<map>
 6 #include<math.h>
 7 //#include<time.h>
 8 //#include<complex>
 9 #include<algorithm>
10 using namespace std;
11 
12 int n;
13 int list[22],num[22],len=0;
14 
15 #define LL long long
16 LL ans;
17 void dfs(int cur,int now,int s)
18 {
19     if (cur>len)
20     {
21         int p=now;
22         for (int i=1;i<=len;i++) if ((s>>(i-1))&1) p=p/list[i]*(list[i]-1);
23         ans+=n/now*p; return;
24     }
25     dfs(cur+1,now,s);
26     for (int i=1,tmp=list[cur];i<=num[cur];i++,tmp*=list[cur]) dfs(cur+1,now*tmp,s|(1<<(cur-1)));
27 }
28 
29 int main()
30 {
31     scanf("%d",&n);
32     int tnt=n;
33     for (int i=2;1ll*i*i<=tnt;i++) if (tnt%i==0)
34     {
35         list[++len]=i;
36         while (tnt%i==0) tnt/=i,num[len]++;
37     }
38     if (tnt) {list[++len]=tnt; num[len]=1;}
39     ans=0; dfs(1,1,0); printf("%lld
",ans);
40     return 0;
41 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8484466.html