H 最大公约数

题意:给出n个数(1~n) 然后让我们通过给出另一个数字y来猜给出的k是否就是最后答案;

判定为最后答案的条件就是:与范围内其他任何数字gcd之后,得出来的数字不等于gcd(y,k);

也就是说,要gcd(y,k)唯一;

思路:我们先来分析两种情况

1. 当y<k时,1<=gcd(k,y)<=y,那么gcd(gcd(k,y),y)就会等于gcd(k,y),不成立;

2. 当y>=k时,1<=gcd(k,y)<=k,那么gcd(gcd(k,y),y)就会等于gcd(k,y);   

在第二种情况下,当y不是k的倍数的时候,得出来的gcd<k,而这个小于k的数与y再gcd,肯定也等于这个小于k的数(类似第一种情况)不成立

所以只有当y为k的倍数的时候,得出来的gcd才有可能是答案;

假设数据范围为(1~20) k为4  那么我们要找到一个y满足gcd(k,y)=k,然后其他k的倍数的数与y gcd之后也是k的倍数,然后此y值就是最后答案;

那么如何求出y呢,我们先将所有k的倍数的数/k,那么假如y为得出的数相乘,自然也能够满足答案,可是不是最小答案;

这里又有些数论的简单知识, 倘若我们处理完毕之后,有k的倍数1 2 3 4 5 6,那么要想得出最小的答案,便是将所有素数相乘即可;

为何呢?首先我们看看比2大的偶数,这些数肯定不需要乘了,因为这些数(2,gcd)=2,也就是说,只要最后得出的y与后面这些比2大的偶数

             的公倍数,是2*k即可;

所以可以得出,只要是合数,与y得出的公倍数是其质因子(质因子肯定是前面的数构成)*k即可;

所以,就是将答案*这些数的素数即可; 

y就要等于k与[1,n]区间k的倍数除去k后都质因数分解后所有不同的质数的乘积相乘即可;

这样可以保证求出来的y对于k的其他倍数的gcd不等于k,同时y又是满足题意的最小值。

但是最后答案可能为大整数,所以需要打大数代码;

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int ans[2000],cnt;
 4 void cal(int t)
 5 {
 6     for(int i=0;i<cnt;i++) ans[i]*=t;
 7     for(int i=0;i<cnt;i++)
 8     {
 9         if(ans[i]>=10)
10         {
11             if(i==cnt-1) cnt++;
12             while(ans[i]>=100) ans[i]-=100,ans[i+1]+=10;
13             while(ans[i]>=10) ans[i]-=10,ans[i+1]++;
14         }
15     }
16 }
17 int main()
18 {
19     int ar[600]={1,1,0};
20     for(int i=2;i<=sqrt(500+0.5);i++)
21     {
22         if(!ar[i])
23         {
24             for(int j=i*i;j<=500;j+=i)
25                 ar[j]=1;
26         }
27     }
28     int t,n,k;
29     cin>>t;
30     while(t--){
31         cin>>n>>k;
32         memset(ans,0,sizeof ans);
33         ans[0]=1; cnt=1;
34         cal(k);
35         for(int i=2;i*k<=n;i++)
36             if(!ar[i]) cal(i);
37         for(int i=cnt-1;i>=0;i--) cout<<ans[i];
38         cout<<endl;
39     }
40     return 0;
41 }

 

posted @ 2020-03-11 13:26  古比  阅读(231)  评论(0编辑  收藏  举报