题目大意:求gcd(1,2)+gcd(1,3)+gcd(2,3)+...+gcd(n-1,n)
-----------------------------------------------------------------
设f(i)=gcd(1,n)+...+gcd(n-1,n),则答案S(n)=f(2)+...+f(n)
如何求f
设g(n,i)表示满足gcd(x,n)=1且x<n的x个数,则f(n)=sum{i*g(n,i):i|n}
gcd(x,n)=i的充要条件是x/i和n/i互质,所以gcd(n,i)=phi(n/i)
计算一片f用类似筛法的方法
------------------------------------
LuoguP2398题目描述
for i=1 to n
for j=1 to n
sum+=gcd(i,j)
给出n求sum. gcd(x,y)表示x,y的最大公约数.
----------------------------------------
很类似,在加上一个nf=gcd(1,n)+...+gcd(n,n) f和nf加起来就行了
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; const int N=1e5+5; ll n,ans=0; int phi[N]; void phiTable(int n){ phi[1]=1; for(int i=2;i<=n;i++) if(!phi[i]) for(int j=i;j<=n;j+=i){ if(!phi[j]) phi[j]=j; phi[j]=phi[j]/i*(i-1); } } ll f[N],nf[N]; int main(int argc, const char * argv[]) { cin>>n; phiTable(n); for(int i=1;i<=n;i++) for(int j=i;j<=n;j+=i){ nf[j]+=i*phi[j/i]; if(j!=i) f[j]+=i*phi[j/i]; } for(int i=1;i<=n;i++) ans+=f[i]+nf[i]; cout<<ans; return 0; }