题目连接:GCD SUM
分析:题目很简洁。求gcd的和。暴力是不可能过的。考虑所有gcd的值,对于gcd(x,y)=1,都有gcd(xk,yk)=k(xk<=n&&yk<=n),那么gcd(x’,y’)=k的个数就是2*
∑
i
=
1
n
/
k
\sum_{i=1}^{n/k}
∑i=1n/kf(i) -1 (f(i)为欧拉函数,(x,y)和(y,x)为两组,但是只有当x=y=1时是一组,所以要减一。)
代码:
#include<iostream>
#define IOS ios::sync_with_stdio(false);
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<deque>
using namespace std;
typedef long long ll;
typedef double dd;
typedef pair<int, int> PII;
const int N=1e6+10;
int dx[4]={-1,0,0,1};
int dy[4]={0,1,-1,0};
int lowbit(int x){
return x&-x;
}
int n;
int prim[N];
ll sum[N];
ll cont[N];
bool st[N]{};
int nu=0;
void init(){//欧拉函数模板
cont[1]=1;
int m=1e5;
for(int i=2;i<=m;i++){
if(!st[i]) prim[nu++]=i,cont[i]=i-1;
for(int j=0;prim[j]*i<=m;j++){
st[prim[j]*i]=1;
if(i%prim[j]==0){
cont[i*prim[j]]=prim[j]*cont[i];
break;
}
cont[i*prim[j]]=(prim[j]-1)*cont[i];
}
}
for(int i=1;i<=m;i++) sum[i]=sum[i-1]+cont[i];
}
int main(){
cin>>n;
init();
//cout<<"YES"<<endl;
ll ans=0;
for(int i=1;i<=n;i++){//枚举每一个k
ans+=(sum[n/i]*2-1)*i;
}
cout<<ans;
return 0;
}