求和 gcd(i,j)
转化为 k*gcd(i/k,j/k) = 1 (i,j%k = 0)。
本质就是利用互质转化到了欧拉函数的领域上。
[SDOI2012] Longge 的问题 - 洛谷
转自小粉兔
#include<bits/stdc++.h>
#define int long long
using namespace std;
unordered_map<int,int>pd;
long long ans,n;
vector<int> breakdown(int N) {
vector<int> result;
for (int i = 2; i * i <= N; i++) {
if (N % i == 0) { // 如果 i 能够整除 N,说明 i 为 N 的一个质因子。
pd[i] = 1;
while (N % i == 0) N /= i;
result.push_back(i);
}
}
if (N != 1) { // 说明再经过操作之后 N 留下了一个素数
result.push_back(N);
pd[N] = 1;
}
return result;
}
int phi(int n){
if(pd[n])return n-1;
int ans = n;
for(int i = 2;i*i <= n;i++){
if(n%i == 0){
ans = ans/i*(i-1);
while(n%i == 0)n/=i;
}
}
if(n > 1)ans = ans/n *(n-1);
return ans;
}
signed main(){
// cout<<sqrt(pow(2,32));
cin>>n;
breakdown(n);
for(long long i = 1;i * i <= n;i++){
if(n%i == 0){
ans += i*phi(n/i);
if(n/i != i)ans += (n/i)*phi(i);
}
}
cout<<ans;
return 0;
}