1188 最大公约数之和 V2

题目来源: UVA
基准时间限制:2 秒 空间限制:262144 KB 
给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和。
 
 
 
相当于计算这段程序(程序中的gcd(i,j)表示i与j的最大公约数):
 
G=0;
for(i=1;i<N;i++)
for(j=i+1;j<=N;j++)
{
    G+=gcd(i,j);
}
 
Input
第1行:1个数T,表示后面用作输入测试的数的数量。(1 <= T <= 50000)
第2 - T + 1行:每行一个数N。(2 <= N <= 5000000)
Output
共T行,输出最大公约数之和。
Input示例
3
10
100
200000
Output示例
67
13015
143295493160
思路:欧拉函数;
http://www.cnblogs.com/zzuli2sjy/p/5831575.html是这个题的加强版,这里用筛法求欧拉函数,然后再用类似筛法的方法求每个数的约数对答案的贡献,最后求下前缀和
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<string.h>
 5 #include<queue>
 6 #include<math.h>
 7 #include<set>
 8 #include<vector>
 9 #include<string.h>
10 using namespace std;
11 typedef long long LL;
12 bool prime[5000005];
13 int oula[5000005];
14 int ans[5000005];
15 LL ask[5000005];
16 int main(void)
17 {
18     int i,j;
19     int T,N;
20     for(i = 2; i <= 3000; i++)
21     {
22         if(!prime[i])
23         {
24             for(j = i; (i*j)<=5000005; j++)
25             {
26                 prime[i*j]=true;
27             }
28         }
29     }
30     int cn = 0;
31     for(i = 2; i <= 5000000; i++)
32     {
33         if(!prime[i])
34         {
35             ans[cn++]=i;
36         }
37     }
38     for(i = 0; i <= 5000000 ; i++)
39         oula[i]=i;
40     oula[1]=0;
41     memset(ask,0,sizeof(ask));
42     for(i = 0; i < cn; i++)
43     {
44         for(j = 1; j*ans[i] <= 5000000 ; j++)
45         {
46             oula[j*ans[i]]/=ans[i];
47             oula[j*ans[i]]*=ans[i]-1;
48         }
49     }
50     for(i = 1; i <= 5000000; i++)
51     {
52         for(j = 2; (i*j) <= 5000000; j++)
53         {
54             ask[i*j]+=oula[j]*i;
55         }
56     }
57     for(i = 2;i <= 5000000; i++)
58     {
59         ask[i]+=ask[i-1];
60     }
61     scanf("%d",&T);
62     while(T--)
63     {
64         scanf("%d",&N);
65         printf("%lld\n",ask[N]);
66     }
67     return 0;
68 }

 


posted @ 2016-09-02 17:34  sCjTyC  阅读(307)  评论(0编辑  收藏  举报