HDU 5207 Greatest Greatest Common Divisor

题目链接:

hdu:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=153598

bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=577&pid=1002

题解:

1、对于每个输入,枚举它的因子,并统计,结果存在mmp数组中,最后再倒过来扫一遍mmp数组,其中第一个mmp[i]>=2的,就是答案。

  时间复杂度:O(n*sqrt(n) )

这个跑了1404ms

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 const int maxn=1e5+10;
 7 typedef long long LL;
 8 
 9 int n;
10 int mmp[maxn];
11 
12 void init(){
13     memset(mmp,0,sizeof(mmp));
14 }
15 
16 int main() {
17     int tc,kase=0;
18     scanf("%d",&tc);
19     while(tc--) {
20         scanf("%d",&n);
21         init();
22         for(int i=0;i<n;i++){
23             int x;
24             scanf("%d",&x);
25             for(int div=1;div*div<=x;div++){
26                 if(x%div==0){
27                     mmp[div]++;
28                     if(x/div!=div) mmp[x/div]++;
29                 }
30             }
31         }
32         int ans=1;
33         for(int i=maxn-1;i>=0;i--){
34             if(mmp[i]>=2){
35                 ans=i; break;
36             }
37         }
38         printf("Case #%d: %d\n",++kase,ans);
39     }
40     return 0;
41 }
View Code

2、用筛法预处理出10^5以内所有数的因子,然后采用同上的方法做。

筛法的时间复杂度:O(n+n/2+n/3+n/4+...n/n)=O(n*(1+1/2+1/3+...1/n))=O(n*logn)

(附:欧拉公式:1+1/2+1/3+……+1/n=ln(n)+C)

这个跑了374ms

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector> 
 5 using namespace std;
 6 
 7 const int maxn=1e5+10;
 8 typedef long long LL;
 9 
10 int n;
11 int mmp[maxn];
12 vector<int> Div[maxn];
13 
14 void pre_for_div(){
15     for(int i=1;i<maxn;i++){
16         for(int t=i;t<maxn;t+=i){
17             Div[t].push_back(i);    
18         }
19     }
20 }
21 
22 void init(){
23     memset(mmp,0,sizeof(mmp));
24 }
25 
26 int main() {
27     pre_for_div();
28     int tc,kase=0;
29     scanf("%d",&tc);
30     while(tc--) {
31         scanf("%d",&n);
32         init();
33         for(int i=0;i<n;i++){
34             int x;
35             scanf("%d",&x);
36             for(int j=0;j<Div[x].size();j++){
37                 mmp[Div[x][j]]++;
38             }
39         }
40         int ans=1;
41         for(int i=maxn-1;i>=0;i--){
42             if(mmp[i]>=2){
43                 ans=i; break;
44             }
45         }
46         printf("Case #%d: %d\n",++kase,ans);
47     }
48     return 0;
49 }
View Code

3、先统计每个输入的值出现的个数,存在cnt里面;然后从大到小枚举答案ans=d,求解sum(cnt[d],cnt[d*2],cnt[d*3]...),如果sum>=2说明答案就是d。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector> 
 5 using namespace std;
 6 
 7 const int maxn=1e5+10;
 8 typedef long long LL;
 9 
10 int n;
11 int cnt[maxn];
12 
13 void init(){
14     memset(cnt,0,sizeof(cnt));  
15 }
16 
17 int main() {
18     int tc,kase=0;
19     scanf("%d",&tc);
20     while(tc--) {
21         scanf("%d",&n);
22         init();
23         for(int i=0;i<n;i++){
24             int x;
25             scanf("%d",&x);
26             cnt[x]++;
27         }
28         int ans=1;
29         for(int g=maxn-1;g>=1;g--){
30             int tmp=0;
31             for(int sum=g;sum<maxn;sum+=g){
32                 tmp+=cnt[sum];
33             }
34             if(tmp>=2){
35                 ans=g; break;
36             }
37         }
38         printf("Case #%d: %d\n",++kase,ans);
39     }
40     return 0;
41 }
View Code

 

posted @ 2016-04-17 00:06  fenicnn  阅读(231)  评论(0编辑  收藏  举报