# LOJ #6539 奇妙数论题

LOJ#6539

### 题解

$$\sum_{x|a,x|b}\varphi(x)=\gcd(a,b)$$

\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^n(a_i,a_j)·(i,j)\\ &=\sum_{i=1}^n\sum_{j=1}^n(\sum_{x|i,x|j}\varphi(x))(a_i,a_j)\\ &=\sum_{x=1}^n\varphi(x)\sum_{x|i}\sum_{x|j}(a_i,a_j) \end{aligned}

\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^n\gcd(a_i,a_j)\\ &=\sum_{d=1}^n\varphi(d)(\sum_{i=1}^n[d|a_i])^2 \end{aligned}

### 代码

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define rt register int
#define ll long long
using namespace std;
ll x=0;char zf=1;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-1,ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf;
}
void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans;
#define N 100000
bool pri[N+10];int ss[N+10],phi[N+10];
void init(){
phi[1]=1;
for(rt i=2;i<=N;i++){
if(!pri[i]) ss[++cnt]=i,phi[i]=i-1;
for(rt j=1;j<=cnt&&i*ss[j]<=N;j++){
phi[i*ss[j]]=phi[i]*phi[ss[j]];
pri[i*ss[j]]=1;
if(i%ss[j]==0){
phi[i*ss[j]]=phi[i]*ss[j];
break;
}
}
}
}
int a[100010],sum[100010];
vector<int>ys[100010];
ll calc2(int x){
ll ret=0;
for(rt i=x;i<=n;i+=x)sum[a[i]]++;
for(rt i=1;i<=n;i++){
int now=0;
for(rt j=i;j<=n;j+=i)now+=sum[j];
ret+=1ll*phi[i]*now*now;
}
for(rt i=x;i<=n;i+=x)sum[a[i]]=0;
return ret;
}
ll calc(int x){
ll ret=0;
for(rt i=x;i<=n;i+=x){
for(auto j:ys[a[i]]){
ret+=(sum[j]*2+1)*phi[j];
sum[j]++;
}
}
for(rt i=x;i<=n;i+=x){
for(auto j:ys[a[i]])sum[j]=0;
}
return ret;
}
int main(){
for(rt i=1;i<=n;i++)
for(rt j=i;j<=n;j+=i)ys[j].push_back(i);
ll ans=0;
for(rt x=1;x<=n;x++){
if(x<=10)ans+=1ll*phi[x]*calc2(x);else
ans+=1ll*phi[x]*calc(x);
}
cout<<ans%1000000007;
return 0;
}

posted @ 2019-04-03 19:35  Kananix  阅读(258)  评论(0编辑  收藏