赤裸裸的模板题吧
一个大数,判断是否是素数,如果是合数输出最小的因子。
大数的素数测试,随机算法Miller_Rabin测试,前提是了解费马小定理。不过对于非平方根处有疑惑,还得请教大牛
至于输出最小因子,运用Pollard_Rho即可,也算是随机算法,怎么看都是要靠RP的,至于xi=xi-1^2+c ,这个c的取法一直不理解,我用的是240,有的人是使用随机数,网上有大牛说12323速度最快?
/* ID:cxlove PROB:poj 1811 HINT:Miller_Rabin+Pollard_Rho */ #include<iostream> #include<cstdio> #include<ctime> #include<cstring> #include<cstdlib> #define C 240 #define TIME 10 #define LL long long using namespace std; LL ans; LL gcd(LL a, LL b){ if(a==0) return 1; if(a<0) return gcd(-a,b); return b==0?a:gcd(b,a%b); } LL MultMod(LL a,LL b,LL n){ a%=n; b%=n; LL ret=0; while(b){ if(b&1){ ret+=a; if(ret>=n) ret-=n; } a=a<<1; if(a>=n) a-=n; b=b>>1; } return ret; } LL PowMod(LL a,LL n,LL m){ LL ret=1; a=a%m; while(n>=1){ if(n&1) ret=MultMod(ret,a,m); a=MultMod(a,a,m); n=n>>1; } return ret; } bool Witness(LL a,LL n){ LL t=0,u=n-1; while(!(u&1)){ t++; u/=2; } LL x0=PowMod(a,u,n); for(int i=1;i<=t;i++){ LL x1=MultMod(x0,x0,n); if(x1==1&&x0!=1&&x0!=(n-1)) return true; x0=x1; } if(x0!=1) return true; return false; } bool Miller_Rabin(LL n,int t){ if(n==2) return true; if((n&1)==0) return false; srand(time(NULL)); for(int i=0;i<t;i++){ LL a=rand()%(n-1)+1; if(Witness(a,n)) return false; } return true; } LL Pollard_Rho(LL n,LL c){ LL i=1,x=rand()%n,y=x,k=2; while(1){ i++; x=(MultMod(x,x,n)+c)%n; LL d=gcd(y-x,n); if(d!=1&&d!=n) return d; if(x==y) return n; if(i==k){ y=x; k*=2; } } } void get_small(LL n,LL c){ if(n==1) return; if(Miller_Rabin(n,TIME)){ ans=min(n,ans); return ; } LL p=n; while(p>=n) p=Pollard_Rho(p,c--); get_small(p,c); get_small(n/p,c); } int main(){ srand(time(NULL)); LL n; int t; scanf("%d",&t); while(t--){ scanf("%I64d",&n); if(Miller_Rabin(n,TIME)) printf("Prime\n"); else{ans=n; get_small(n,C); printf("%I64d\n",ans); } } return 0; }