uva-11426-数论

https://vjudge.net/problem/UVA-11426#author=0

求 SUM{ gcd(i,j) | 1<=i<j<=n}, n<4000001。

令f(n)=gcd(1,n)+gcd(2,n)+...+gcd(n-1,n),

则 S(n)=f(2)+f(3)+...+f(n) 即为我们所求答案,问题转化为求解f(n)。

  可以看出对于f(n)的所有项的答案一定是n的因子,我们不妨令g(x,i)表示因子i对应的f(n)里的项x的个数,

那么f(n)=SUM{ i*g(x,i) | i为n的因子且0<x<n}  有gcd(x,n)==i  -->  gcd(x/i,n/i)==1 ,所以因子i对应的x的个数就

等价于与n/i互质且小于n/i的数的个数,这个就可以用phi来求解了。

   在求f的时,一开始是用的O(N*sqrt(N))来一个一个找会T,太蠢了。只要和打表phi一样利用类似于埃筛

的方法就可以降到O(N*log(N))了。

  

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long 
 4 const int maxn=4000001;
 5 LL f[maxn];
 6 int phi[maxn];
 7 void init(){
 8     phi[1]=1;
 9     int m=sqrt(maxn+0.5);
10     for(int i=2;i<maxn;++i){
11         if(!phi[i]){
12             for(int j=i;j<maxn;j+=i){
13                 if(!phi[j]) phi[j]=j;
14                 phi[j]=phi[j]/i*(i-1);
15             }
16         }
17     }
18     for(int i=1;i<maxn;++i){
19         for(int j=i*2;j<maxn;j+=i){
20             f[j]+=i*phi[j/i];
21         }
22     }
23     for(int i=3;i<maxn;++i) f[i]+=f[i-1];
24 }
25 int main(){
26     init();
27     int n;
28     while(scanf("%d",&n)&&n){
29         printf("%lld
",f[n]);
30     }
31     return 0;
32 } 
原文地址:https://www.cnblogs.com/zzqc/p/9364628.html