POJ_2635_The Embarassed Cryptographer_同余定律

来源:互联网 发布:长兴岛造船基地 知乎 编辑:程序博客网 时间:2024/06/09 15:06

A题就外放小苹果666。


题意:

密码学背景,给一个大数(10^100),由两个素数相乘得到,给一个10^6以内的l,问这个大数最小的因数是否小于l。


Input

The input consists of no more than 20 test cases. Each test case is a line with the integers 4 <= K <= 10100 and 2 <= L <= 106. K is the key itself, a product of two primes. L is the wanted minimum size of the factors in the key. The input set is terminated by a case where K = 0 and L = 0.

Output

For each number K, if one of its factors are strictly less than the required L, your program should output "BAD p", where p is the smallest factor in K. Otherwise, it should output "GOOD". Cases should be separated by a line-break.


这个题要素数,所以肯定先用筛法打个素数表,然后对每个大数,循环素数,判断是否能被当前素数整除。10^6之前的素数只有10^5级别个,常数比较大,最多20组数据略坑,素数整除尽量控制在50以内。

首先,要做到判断整除需要用到同余定律,百度百科:


同余公式也有许多我们常见的定律,比如相等律,结合律,交换律,传递律….如下面的表示:
1)a≡a(mod d)
2)a≡b(mod d)→b≡a(mod d)
3)(a≡b(mod d),b≡c(mod d))→a≡c(mod d)
如果a≡x(mod d),b≡m(mod d),则
4)a+b≡x+m (mod d)
5)a-b≡x-m (mod d)
6)a*b≡x*m (mod d )
7)a≡b(mod d)则a-b整除d


因此,可以将大数拆分成很多个十位数或者千进制数或者万进制数这样的办法,具体哪个能过还得测试,每次获得当前的模以后,要乘以下一个数的10的位数次方,这里注意最后以为可能不到进制位数,比如你用千进制,但是最后一个数字只有两位,这时之前的模只要乘以100.


代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>using namespace std;#define mxl 2000100#define mxn 110bool is_prime[mxl];int prime[mxl];int cnt;void set_prime(){memset(is_prime,true,sizeof(is_prime));for(int i=2;i<mxl;++i)if(is_prime[i])for(int j=i*2;j<mxl;j+=i)is_prime[j]=false;cnt=0;for(int i=2;i<mxl;++i)if(is_prime[i])prime[cnt++]=i;}char tem[mxn];int end,a[mxn];int l,len;bool ok(int x){int cur=0;for(int i=0;i<end-1;++i)cur=(cur*1000+a[i])%x;int tem=a[end-1];while(tem){cur*=10;tem/=10;}cur=(cur+a[end-1])%x;if(!cur)return true;return false;}void trans(){len=strlen(tem);end=0;int j;for(int i=0;i<len;){a[end]=0;j=i;while(j<len&&j-i<=2)a[end]=a[end]*10+(tem[j++]-'0');i=j;++end;}}int main(){set_prime();while(scanf("%s%d",tem,&l)!=EOF){if(!strcmp(tem,"0")&&!l)break;trans();int ans=-1;for(int i=0;i<cnt;++i){if(prime[i]>=l)break;if(ok(prime[i])){ans=prime[i];break;}}if(ans==-1)puts("GOOD");elseprintf("BAD %d\n",ans);}return 0;}


0 0
原创粉丝点击