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 }