标签:
看到这题的示意图也是醉了~题意:给你一个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