题意简洁明了。做这题主要是温习一下phi的求法。令gcd(i,n)=k,实际上我们只需要求出有多少个i使得gcd(i,n)=k就可以了,然后就转化成了求phi(n/k)的和,但是n很大,我们不可能预处理出所有的phi,但是因为k的个数是O(sqrt(n))级别的,所以我们只需要求出sqrt(n)个数的phi就可以了,我们先预处理出所有的质因子及其个数,然后dfs一下就可以了。
#pragma warning(disable:4996)
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
int n;
int cnt[35];
int prime[35];
int tot;
ll ans;
void dfs(int step, int phi)
{
if (step == tot){
ans += (ll)phi; return;
}
dfs(step + 1, phi);
phi = phi / prime[step] * (prime[step] - 1);
for (int i = 0; i < cnt[step]; i++){
dfs(step + 1, phi);
}
}
int main()
{
while (~scanf("%d",&n))
{
memset(cnt, 0, sizeof(cnt)); tot = 0;
int x = n;
for (ll i = 2; i*i <= x; i++){
if (x%i == 0){
for (; x%i == 0; x /= i) cnt[tot]++;
prime[tot++] = i;
}
if (x == 1) break;
}
if (x != 1) cnt[tot]++, prime[tot++] = x;
ans = 0;
dfs(0, n);
printf("%lld\n", ans);
}
return 0;
}