题意:给出一个大数,这个大数由两个素数相乘得到,让我们判断是否其中一个素数比L要小,如果两个都小,输出较小的那个。
分析:大数求余的方法:针对题目中的样例,143 11,我们可以这样算,1 % 11 = 1; 1×10 + 4 % 11 = 3; 3×10 + 3 % 11 = 0;我们可以把大数拆成小数去计算,同余膜定理保证了这个算法的这正确性,而且我们将进制进行一定的扩大也是正确的。
注意:素数打标需要优化,否则超时。 进制需要适当,100和1000都可以,10进制超时,10000以上WA(不知道为什么……)。 把进制扩大以后,数据必须从后向前存,从前向后存的不是原数。
总结:这个题目卡时间卡的特别紧;
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define maxn 1000010 #define jz 1000 int prime[maxn],tot,List[maxn]; void make_prime() { for(int i = 0; i <= maxn-10; i++) { prime[i] = 1; } prime[0] = prime[1] = 0; int d = sqrt((double)maxn) + 1; for(int i = 2; i <= maxn-10; i++) { if(!prime[i]) continue; List[tot++] = i; if(i > d) continue; for(int j = 2*i; j <= maxn-10; j += i) { prime[j] = 0; } } } int mypow(int x,int y) { int sum = 1; for(int i = 1; i <= y; i++) sum *= x; return sum; } int main() { tot = 0; make_prime(); char str[110]; int l,lens,a[110],ans,num,jw,cnt,number,tot1; while(~scanf("%s%d",str,&l)) { if(str[0] == '0' && l == 0) break; lens = strlen(str); cnt = 0; number = 0; tot1 = 0; for(int i = lens-1; i >= 0; i--) { num = str[i] - '0'; number += num * mypow(10,cnt); // printf("number = %d ",number); cnt++; if(cnt == 3) { cnt = 0; a[tot1++] = number; number = 0; } } if(number) a[tot1++] = number; bool flag = true; for(int i = 0; i < tot; i++) { jw = 0; num = List[i]; if(num >= l) break; for(int j = tot1-1; j >= 0; j--) { jw = (jw*jz + a[j]) % num; } if(jw == 0) { flag = false; ans = num; break; } } if(flag) { puts("GOOD"); } else printf("BAD %d ",ans); memset(a,0,sizeof(a)); memset(str,0,sizeof(str)); } return 0; }