poj2635(千进制取模+同余模定理)
题目链接:https://www.cnblogs.com/kuangbin/archive/2012/04/01/2429463.html
题意:给出大数s (s<=10100) ,L (<=106),s是两个素数的乘积,求其最小因子即这两个素数中较小者是否小于L。
思路:先通过欧筛法打表计算出106以内的素数,大概有8e4个。然后用千进制表示s,如将12345678表示成[012][345][678],用整型数组Kt表示,前面补0,这样做之后利用同余模定理计算Kt对x的模。如计算[012][345][678]%10,记模为M,则M=0, M=12%10=2, M=(2*1000+345)%10=5, M=(5*1000+678)%10=8。然后主要思路就是从小遍历打表得出的素数表,寻找是否存在能整除Kt的素数。用千进制的原因是为了降低复杂度,据说用百进制会T,万进制会wa(可能计算过程会超int)。
AC代码:
#include<cstdio> #include<iostream> #include<cstring> #include<string> using namespace std; const int maxn=1000005; int prime[maxn],vis[maxn],cnt,L,len1,len2,Kt[35]; string s; void get_prime(){ memset(vis,1,sizeof(vis)); for(int i=2;i<=1000000;++i){ if(vis[i]) prime[cnt++]=i; for(int j=0;j<cnt&&i*prime[j]<=1000000;++j){ vis[i*prime[j]]=0; if(i%prime[j]==0) break; } } } bool Mod(int x){ int M=0; for(int i=0;i<len2;++i) M=(M*1000+Kt[i])%x; return M==0?true:false; } int main(){ get_prime(); while(cin>>s>>L,(s[0]!='0')||L){ len1=s.length(); if(len1%3==1) s="00"+s; else if(len1%3==2) s="0"+s; len1=s.length(); len2=len1/3; for(int i=0;i<len2;++i) Kt[i]=(s[3*i]-'0')*100+(s[3*i+1]-'0')*10+(s[3*i+2]-'0'); bool flag=true; int p=0; while(p<cnt&&prime[p]<L){ if(Mod(prime[p])){ flag=false; printf("BAD %d\n",prime[p]); break; } ++p; } if(flag) printf("GOOD\n"); } return 0; }
朋友们,无论这个世界变得怎样,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。