题意:求∑ni=1gcd(i,n)
首先,gcd(i,n)肯定是n的约数。所以我们可以考虑枚举每个n的约数d,然后看有多少个gcd(i,n)=d。这个式子又可以化成gcd(i/d,n/d)=1。而它,就相当于ϕ(n/d)。所以,答案就是∑d|nϕ(n/d),其中ϕ(x)可以在O(x√)的时间内求出。
// BZOJ 2705
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
#define read(x) scanf("%lld", &x)
LL n;
LL phi(LL x) {
LL ret=x;
for (LL i=2; i*i<=n; i++)
if (x%i==0) {
ret=ret/i*(i-1); // 先除后乘防溢出
while (x%i==0) x/=i;
}
if (x>1) ret=ret/x*(x-1); // x is a prime
return ret;
}
int main()
{
read(n);
LL ans=0;
for (LL i=1; i*i<=n; i++)
if (n%i==0) {
ans+=(LL)i*phi(n/i);
ans+=(LL)(n/i)*phi(i);
}
printf("%lld
", ans);
return 0;
}