poj 2635 The Embarrassed Cryptographer

//poj6 2635 The Embarrassed Cryptographer

//题意: 给定4 ≤ K ≤ 10^100 和 2 ≤ L ≤ 10^6 ,问 K 是否存在小于L的素因数
//由于这里K值很大,如果用普通的高精度来计算,那么将会TLE,
//《全国信息学奥林匹克联赛培训教程<二>》中介绍了一种方法来改善高精度运算的效率:扩大进制数.
//用整数数组每一个元素表示一个十进制整数的方法存在的缺点是:如果十进制的位数很多,则对应的数组的长度会很长,并增加了高精度计算的时间。
//理论上来说,高精度运算所用的数组中的每个数表示的数字越多,数组的长度就越小,程序运行的时间也就越短,但是,我们还需要考虑到计算机中的一个数的取值范围,必须保证它们在运算过程中不会越界,
//在权衡了两方面的情况后得出,将数组中的每个数字来记录4位数字是最佳的方案,那么在这个数组的一个元素就相当于一个10000进制的数,其中每一个元素都是10000进制下的一位数.
//按照上面的方法,数组中的每一个元素采用10000进制来存储4位数,但是WA了,将数组中的每一个元素改为1000进制来存储3位数才AC掉.而看到的解释是由于int的存储能力有限,所以我们只能使用1000进制.
//由于这题要求最小的素数因子,所以先要打表生成所有的素数,然后还要使用高精度来求余.


#include <iostream> //大数表示法,扩大进制数--1000进制
#include <string>

using namespace std;
#define MAXN 1000002
bool isPrime[MAXN];
int tot,prime[100000];
void makePrime() //线性筛法建立素数表
{

memset(isPrime,true,sizeof(isPrime));
tot=0;
for(int i=2;i<=MAXN;i++)
{
if(isPrime[i])
prime[++tot]=i; //素数表prime[1]-prime[tot]
for(int j=1; j<=tot && i*prime[j]<=MAXN; ++j)

{
isPrime[i*prime[j]]=false;
if(i%prime[j]==0)
break;
}
}
}

string str;
int L,num[40],rear;
void trans() //1000进制表示大数
{

int len=str.size();
rear=len/3+len%3;
int j=rear;
for(int i=len-1;i>=0;i-=3) //1234567890转成千进制,就变成了:[1][234][567][890]
{

num[j]=0;
for(int k=max(i-2,0);k<=i;++k) //数组第一个元素可能不足3位
num[j]=10*num[j]+str[k]-'0';

j--; //num[rear]-num[1]
}

}
int mod(int d) //高精度取余
{

int res=0,s=0;
for(int i=1;i<=rear;++i)
{
s=1000*res+num[i];
res=s%d;
}
return res;
}
int main()
{
makePrime();
while(cin>>str>>L&&L)
{
trans();
int ok=1;
for(int i=1;i<=tot&&prime[i]<L;++i)
{
if(mod(prime[i])==0)
{
printf("BAD %d\n",prime[i]);
ok=0;
break;
}
}
if(ok)
printf("GOOD\n");
}
return 0;
}

posted on 2011-05-10 10:57  sysu_mjc  阅读(232)  评论(0编辑  收藏  举报

导航