BestCode#38 B

题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=577&pid=1002

题目大意:在n个数里面任选两个x,y找出里面gcd(x,y)最大的gcd值。

解析:由于n的范围是2到10w,所以暴力枚举肯定超时。

解法一:对于输入的n 个数依次求出他们的因子,将因子个数记录在ant[]数组内。我们容易知道,如果一个因子的个数超过2 的话,那么这个因子必为公因子。所以我们只需要寻找这些公因子里面最大的那个就可以了。详细代码如下:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define max(x,y) x>y?x:y
 5 using namespace std;
 6 
 7 int ant[1000006];
 8 int a[1000006];
 9 int main()
10 {
11     int t;
12     scanf ("%d",&t);
13     for(int i=1;i<=t;i++)
14     {
15         int n,maxp=1;
16         memset(ant,0,sizeof(ant));
17         scanf ("%d",&n);
18         for(int j=0;j<n;j++)
19         {
20             scanf ("%d",&a[j]);
21             for(int k=1;k<=a[j];k++)//计算n个数的因子,因子个数存放在ant[]数组内
22             {
23                 if(a[j]%k==0)
24                     ant[k]++;
25             }
26             maxp=max(maxp,a[j]);
27         }
28         int ans=1;
29         for(int j=1;j<=maxp;j++)
30         {
31             if(ant[j]>=2)//寻找公因子找到最大的那个公因子
32                 ans=max(ans,j);
33         }
34         printf("Case #%d: %d\n",i,ans);
35     }
36     return 0;
37 }

解法二:首先maxp是n个数里的最大数。那么这个最大公因子必然在1~maxp之间。那么我们可以直接在maxp~1之间枚举每个数k,判断在n个数里面是否有2个或者更多的k的倍数。一旦找到这样的数k,那么可以断定k就是答案。直接跳出循环。不需要执行以后的循环了,节约了大部分时间。代码如下:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 int ant[1000006],a[1000006];
 7 int main()
 8 {
 9     int t;
10     scanf ("%d",&t);
11     for(int i=1;i<=t;i++)
12     {
13         memset(ant,0,sizeof(ant));
14         int maxp=1,n,j,k;
15         scanf ("%d",&n);
16         for(j=1;j<=n;j++)
17         {
18             scanf ("%d",&a[j]);
19             maxp=max(maxp,a[j]);
20             ant[a[j]]++;
21         }
22         int flag=0;
23         for(j=maxp;j>=1;j--)//从maxp~1枚举每个数
24         {
25             int num=0;
26             for(k=j;k<=maxp;k=k+j)
27             {
28                 if(ant[k])//寻找k的倍数的个数。
29                     num+=ant[k];
30                 if(num>1)//一旦找到了这样的数j,他的倍数个数大于1,则直接跳出循环。
31                 {
32                     flag=1;
33                     printf("Case #%d: %d\n",i,j);
34                     break;
35                 }
36             }
37             if(flag)
38                 break;
39         }
40     }
41     return 0;
42 }

 

结论:当暴力不能解决问题的时候需要转个弯,从问题的深层次来思考,或者想出一种巧妙的办法,理解问题,拆开问题,才能不断打开思路。

posted on 2015-04-19 00:57  Bei_insomia  阅读(195)  评论(0编辑  收藏  举报

导航