uva11426 GCD Extreme(II)

题意:求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
",S[n]);
50     }
51     return 0;
52 }
View Code
原文地址:https://www.cnblogs.com/ITUPC/p/4912971.html