HDU 5207 Greatest Greatest Common Divisor

本文探讨了在解决HDOJ等在线评测平台的编程题目时,通过优化算法来提高运行效率的方法。首先介绍了针对不同输入情况的枚举因子计数策略,接着通过筛法预处理因子,显著减少了计算时间。最后提出了一种基于输入值频次的快速求解方法,进一步提升了解题速度。详细分析了每种方法的时间复杂度,提供了实测结果对比,旨在为编程竞赛和日常编程任务提供高效解决方案。

题目链接:

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

 

转载于:https://www.cnblogs.com/fenice/p/5399888.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值