a[] = {1,2,3,4...n}
n与a[i]的最大公约数,必定属于n的因子,所以遍历n的因子。
对于n的一个因子k,我们求出k作为最大公约数出现的次数m
如何求出m呢:
gcd(n,a[i])==k => gcd(n/k,a[i]/k)==1
这相当与求:小于n/k,且与n/k互质的数的个数,可以用欧拉函数解决
#include<stdio.h> #include<queue> #include<string.h> #include<iostream> #include<algorithm> #define MAXSIZE 1000005 #define LL long long using namespace std; LL Solve(LL n) { LL ans = 1; for(int i=2;i*i<=n;i++) { if(n%i==0) { n /= i; ans *= (i-1); while(n%i==0) { n /= i; ans *= i; } } } if(n > 1) ans *= (n-1); return ans; } int main() { LL n,ans=0; scanf("%lld",&n); for(LL i=1;i*i<=n;i++) { if(n%i!=0) continue; ans += i*Solve(n/i); if(i != n/i) { ans += (n/i)*Solve(n/(n/i)); } } printf("%lld\n",ans); return 0; }