UVA 11426(欧拉函数)
求∑i=2N−1∑j=i+1Ngcd(i,j)\sum_{i=2}^{N-1}\sum_{j=i+1}^Ngcd(i,j)i=2∑N−1j=i+1∑Ngcd(i,j)
一开始想过用莫比乌斯反演做…然而做不出来。
解:
∑i=1N−1∑j=i+1Ngcd(i,j)=∑i=2N∑j=1i−1gcd(i,j)\sum_{i=1}^{N-1}\sum_{j=i+1}^Ngcd(i,j)=\sum_{i=2}^N\sum_{j=1}^{i-1}gcd(i,j)i=1∑N−1j=i+1∑Ngcd(i,j)=i=2∑Nj=1∑i−1gcd(i,j)
gcd(i,j)=dgcd(i,j)=dgcd(i,j)=d等价于gcd(id,jd)=1gcd(\frac{i}{d},\frac{j}{d})=1gcd(di,dj)=1
既然直接求gcd(i,j)gcd(i,j)gcd(i,j)比较难,那么我们是否可以求满足[gcd(i,j)==1][gcd(i,j)==1][gcd(i,j)==1]的(i,j),j<i(i,j),j<i(i,j),j<i,这样每对(k∗i,k∗j)(k*i,k*j)(k∗i,k∗j)对答案的贡献就是kkk。
因为jjj严格小于iii,gcd(i,j)==1gcd(i,j)==1gcd(i,j)==1的个数就是ϕ(i)\phi(i)ϕ(i)。
现在考虑kkk的取值范围,因为要满足1≤j<i≤n1\le j<i\le n1≤j<i≤n,所以易得kkk的取值范围是1≤k≤⌊ni⌋1\le k\le \lfloor\frac{n}{i}\rfloor1≤k≤⌊in⌋。
那么每个iii对答案的贡献就是1+2+...+⌊ni⌋1+2+...+\lfloor\frac{n}{i}\rfloor1+2+...+⌊in⌋
∑i=1N−1∑j=i+1Ngcd(i,j)=∑i=2N∑j=1i−1gcd(i,j)=∑i=2Nϕ(i)(1+⌊ni⌋)⌊ni⌋2\begin{aligned} \sum_{i=1}^{N-1}\sum_{j=i+1}^Ngcd(i,j)&=\sum_{i=2}^N\sum_{j=1}^{i-1}gcd(i,j)\\ &=\sum_{i=2}^N\phi(i)\frac{(1+\lfloor\frac{n}{i}\rfloor)\lfloor\frac{n}{i}\rfloor}{2} \end{aligned}i=1∑N−1j=i+1∑Ngcd(i,j)=i=2∑Nj=1∑i−1gcd(i,j)=i=2∑Nϕ(i)2(1+⌊in⌋)⌊in⌋
时间复杂度O(tn)+O(N)O(tn)+O(N)O(tn)+O(N)
#include<bits/stdc++.h>
using namespace std;
const int max_n=4e6+5;
int prime[max_n];
int vis[max_n];
int cnt=0;
int e[max_n];
void init(void)
{
for(int i=2;i<max_n;i++)
{
if(!vis[i]){
prime[cnt++]=i;
e[i]=i-1;
}
for(int j=0;j<cnt&&i*prime[j]<max_n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0){
e[i*prime[j]]=e[i]*prime[j];
break;
}
e[i*prime[j]]=e[i]*e[prime[j]];
}
}
}
int main(void)
{
int n;
init();
while(~scanf("%d",&n)&&n)
{
long long ans=0,t;
for(int i=2;i<=n;i++)
{
t=n/i;
t=(1+t)*t/2;
ans+=1ll*e[i]*t;
}
printf("%lld\n",ans);
}
}
//10
//100
//200000
//0