标签:
看到这题的示意图也是醉了~题意:给你一个k,他是两个素数之积,然后给了一个数字L,然后找到具体是哪两个素数相乘等于k,较小的那个素数是否小于L,若小于L就输出 "BAD"外加较小的那个素数,否则就输出“GOOD”,
刚拿到这题目,有些钻牛角尖外加题意没看清楚,一开始纠结于 K很大,若想具体找出两个素数不可能,因为总有一个很大很大,求出其中一个素数 是否在10^6内是可以的,但是那时候我觉得还需要证明 k/prime 的值必须也是素数才符合要求,其实题目都规定好了 k必定是两个素数之积 而不会由其它合数相乘构成,所以就简单了许多
我不知道这个是什么定理的,但是对于一个很长的数字 比如 123456789,若把它每位上数字存在数组num中,123456789%m也等于
int now = 0;
for(int i=0;i<9;i++) now = (now * 10 + num[i])%m;
如果知道这个的话就好做了,对于K其实可以转化为大进制的数字存在数组里,比如转化为千进制万进制,先保存好,最后 计算的时候再乘以一千或者一万,上面那个for是相对于十进制的,把那个now*10改成对应进制即可,剩下的枚举素数只需要打印素数表即可,一开始害怕K太大存不下来而没有去细算直接转化为万进制,结果一直WA,后来转化为千进制就过了,原因是 for循环时每次取余的时候,余数最大可达10^6,然后再乘10000就会爆int,然后又改成了 long long,转化为万进制,也是可以过的
string s;
int L;
int nnum[100000 + 5];
int cnt ;
bool isprime[1000000 + 55];
int prime[1000000 + 55];
int k;
void make_prime() {
memset(isprime,false,sizeof(isprime));
for(int i=2;i<1000055 ;i++)
if(!isprime[i])
for(int j=i*2;j<1000055;j+=i)
isprime[j]=true;
for(int i=2;i<1000055;i++)
if(!isprime[i])
prime[k++]=i;
}
void init() {
memset(nnum,0,sizeof(nnum));
cnt = 0;
}
bool input() {
while(cin>>s>>L) {
if(s == "0" && L == 0)break;
return false;
}
return true;
}
void slove() {
int len = s.length();
for(int i=len - 1;i >= 0;i-=3) {
for(int j= i - 2;j<=i;j++) {
if(j < 0)j = 0;
nnum[cnt] = nnum[cnt] * 10 + s[j] - '0';
}
cnt++;
}
}
bool gao(int x) {
int ret = 0;
for(int i= cnt - 1;i>=0;i--) {
ret = (ret * 1000 + nnum[i])%x;
}
if(ret)return false;
return true;
}
void cal() {
slove();
for(int i=0;i<k && prime[i] < L;i++) {
if(gao(prime[i])) {
printf("BAD %d\n",prime[i]);
return ;
}
}
puts("GOOD");
}
void output() {
}
int main() {
make_prime();
while(true) {
init();
if(input())return 0;
cal();
output();
}
return 0;
}
POJ2635 The Embarrassed Cryptographer 简单数论
标签:
原文地址:http://blog.csdn.net/yitiaodacaidog/article/details/45047373