pku 2635 The Embarrassed Cryptographer 数论——素数筛选法+模拟大数除法
http://poj.org/problem?id=2635
因为给定的k是两个素数的乘机,所以该数所包含的因子是{1,K,p,q}假设k = p*q p,q为素数,所以只要从小到大枚举小于L的素数,只要能够整出,就说明p已经求得,否则则不存在。这里关键是k< 10^100次方,普通数据类型无法直接输入,所以要模你除法,这里将k转换成1000进制的数然后模拟除法。如果是10进制的数模拟除法是时间复杂度会是O(10^8)会超时。
View Code
#include <stdio.h> #include <string.h> #define maxn 1000007 int f[maxn],p[maxn]; int ans[40]; char K[107]; int L,len,anslen; //素数筛选法打表 void Prim() { int i,j; len = 0; memset(f,0,sizeof(f)); f[0] = f[1] = 1; for (i = 2; i*i < maxn; ++i) { if (!f[i]) { for (j = 2*i; j < maxn; j = j + i) { f[j] = 1; } } } for (i = 2; i < maxn; ++i) { if (!f[i]) p[len++] = i; } /*for (i = 0; i <= 50; ++i) { printf("%d ",p[i]); } printf("\n");*/ } //将K转化曾1000进制数 void convert() { int i; int lenx = strlen(K); memset(ans,0,sizeof(ans)); anslen = 0; i = 0; if (lenx%3 != 0) { for (; i < lenx%3; ++i) { ans[0] = ans[0]*10 + K[i] - '0'; } anslen++; } //printf(">>>>>>>>>>>%d\n",anslen); while (i < lenx) { ans[anslen] = (K[i] - '0')*100 + (K[i + 1] - '0')*10 + (K[i + 2] - '0'); i += 3; anslen++; //puts("TEST"); } } //模拟除法 int mod(int x) { int i; int tmp = 0; for (i = 0; i < anslen; ++i) { tmp = (ans[i] + tmp*1000)%x; } return tmp; } int main() { int i; Prim(); while (scanf("%s%d",K,&L)) { if (!strcmp(K,"0") && !L) break; convert(); //循环查找 for (i = 0; p[i] < L; ++i) { if (!mod(p[i])) break; } if (p[i] >= L) printf("GOOD\n"); else printf("BAD %d\n",p[i]);; } return 0; }