标签:
题意:求sum(gcd(i,j),1<=i<j<=n)1<n<4000001
思路:
1.建立递推关系,s(n)=s(n-1)+gcd(1,n)+gcd(2,n)+……+gcd(n-1,n);
2.设f(n)=gcd(1,n)+gcd(2,n)+……+gcd(n-1,n)。
gcd(x,n)=i是n的约数(x<n),按照这个约数进行分类。设满足gcd(x,n)=i的约束有g(n,i)个,则有f(n)=sum(i*g(n,i))。
而gcd(x,n)=i等价于gcd(x/i,n/i)=1,因此g(n,i)等价于phi(n/i).phi(x)为欧拉函数。
3.降低时间复杂度。用筛法预处理phi[x]表
用筛法预处理f(x)->枚举因数,更新其所有倍数求解。
1 #include <iostream> 2 #include <cstdio> 3 #include<cstdlib> 4 #include<cctype> 5 #include<cstring> 6 #include<vector> 7 #include<cassert> 8 9 using namespace std; 10 const int maxn = 4000010; 11 #define LL long long 12 #define clc(a,b) memset(a,b,sizeof(a)) 13 LL S[maxn],f[maxn]; 14 LL phi[maxn]; 15 void phi_table(int n) 16 { 17 for(int i=2;i<=n;i++) 18 phi[i]=0; 19 phi[1]=1; 20 for(int i=2;i<=n;i++) 21 { 22 if(phi[i]==0) 23 { 24 for(int j=i;j<=n;j+=i) 25 { 26 if(!phi[j]) 27 phi[j]=j; 28 phi[j]=phi[j]/i*(i-1); 29 } 30 } 31 } 32 } 33 34 int main() 35 { 36 phi_table(maxn); 37 clc(f,0); 38 for(int i=1;i<=maxn;i++) 39 { 40 for(int n=i*2;n<=maxn;n+=i) 41 f[n]+=i*phi[n/i]; 42 } 43 S[2]=f[2]; 44 for(int n=3;n<=maxn;n++) 45 S[n]=S[n-1]+f[n]; 46 int n; 47 while(scanf("%d",&n),n) 48 { 49 printf("%lld\n",S[n]); 50 } 51 return 0; 52 }
标签:
原文地址:http://www.cnblogs.com/ITUPC/p/4912971.html