poj2635 The Embarrassed Cryptographer(高精度 同余取模)

The Embarrassed Cryptographer
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 13831 Accepted: 3762

Description

The young and very promising cryptographer Odd Even has implemented the security module of a large system with thousands of users, which is now in use in his company. The cryptographic keys are created from the product of two primes, and are believed to be secure because there is no known method for factoring such a product effectively.
What Odd Even did not think of, was that both factors in a key should be large, not just their product. It is now possible that some of the users of the system have weak keys. In a desperate attempt not to be fired, Odd Even secretly goes through all the users keys, to check if they are strong enough. He uses his very poweful Atari, and is especially careful when checking his boss' key.

Input

The input consists of no more than 20 test cases. Each test case is a line with the integers 4 <= K <= 10 100 and 2 <= L <= 10 6. 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.

Sample Input

143 10
143 20
667 20
667 30
2573 30
2573 40
0 0

Sample Output

GOOD
BAD 11
GOOD
BAD 23
GOOD
BAD 31


题意:输入两个数K和L,K是两个素数的乘积(这句话告诉我们,这个K的因子除了1和它本身就只有这两个素数了),然后就是问你这两个素数是不是都比L大,如果是那么输出GOOD,不是那就输出BAD+最小的那个素数~

思路:首先我们想一下,可以打一个素数表,从最小的开始枚举,如果K能够整除这个素数,那么说明这个素数就是K的最小的素数了。然后直接和L比较就可以了。

不过人家K给了100位呐,普通的方法肯定是不行的了。我们这就把整除换成取模为0,这个是等价的,但是取模就不一样辣,我们可以用乘10取余法,当然这里是超时的,所以我们只能用乘千取余法辣~其实多少位都是可以的,确保不超时就好啦。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=1000000+10;
bool prim[MAXN];
int primnum[MAXN];
int pcnt,cnt;
int num[50];
void get_prim()//欧拉筛
{
    pcnt=0;
    int i,j;
    for(i=2; i<=1000000; ++i)
    {
        if(prim[i])continue;
        primnum[pcnt++]=i;
        for(j=i*2; j<=1000000; j+=i)prim[j]=1;
    }
}
char k[110];
int l;
int main()
{
    int i,j;
    get_prim();//素数打表
    while(~scanf("%s %d",k,&l))
    {
        if(k[0]=='0'&&!l)break;
        int len=strlen(k);
        cnt=0;
        for(i=0; i<len; i+=3)//3个一分,乘10取余会超时呐
        {
            int h=0;
            for(j=i; j<i+3&&j<len; ++j)
            {
                h=h*10+k[j]-'0';
            }
            num[cnt++]=h;
        }
        int ml=0,x=num[cnt-1];//表示最后可能不满3位,这里记录一下最后一位的位数
        while(x)
        {
            ml++;
            x/=10;
        }
        int flag=1;//默认就是最小素数比L大的
        for(i=0; i<pcnt; ++i)//枚举素数
        {
            if(primnum[i]>=l)break;//确定符合条件,小优化
            int h=0;
            for(j=0; j<cnt-1; ++j)//乘千取余
            {
                h=(h*1000+num[j])%primnum[i];
            }//最后的一个需要特殊处理一下
            if(ml==1)h=(h*10+num[j])%primnum[i];
            else if(ml==2)h=(h*100+num[j])%primnum[i];
            else h=(h*1000+num[j])%primnum[i];
            if(!h)//找到最小的那个素数了,肯定是小于L的,不符合条件
            {
                flag=0;
                break;
            }
        }
        if(flag)printf("GOOD\n");
        else printf("BAD %d\n",primnum[i]);
    
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值