大素数测试和大数素因子分解
发布时间:2021-02-26 03:16:52 所属栏目:大数据 来源:网络整理
导读:小黄书第19章p82页根据合数的拉宾-米勒测试可得到素数的必要条件。 参考资料。 以POJ1811 Prime Test 为例。 #includestdio.h#includemath.h#includestdlib.h#includealgorithmusing namespace std;typedef long long LL;const int S=20;LL pfact[10005],
小黄书第19章p82页根据合数的拉宾-米勒测试可得到素数的必要条件。 参考资料。 以POJ1811 Prime Test 为例。 #include<stdio.h> #include<math.h> #include<stdlib.h> #include<algorithm> using namespace std; typedef long long LL; const int S=20; LL pfact[10005],ant; LL multi_mod(LL a,LL b,LL c){ //防止a*b溢出! LL ans=0; while(b){ if(b&1){ ans=(ans+a)%c; } a<<=1; if(a>=c)a%=c; b>>=1; } return ans; } LL pow_mod(LL a,LL c){ LL ans=1; while(b){ if(b&1){ ans=multi_mod(ans,a,c); } a=multi_mod(a,c); b>>=1; } return ans; } bool check(LL a,LL n,LL x,LL t){ LL ret=pow_mod(a,x,n); // LL last=ret; if(ret==1||ret==n-1)return false;//根据合数的拉宾-米勒测试. 满足a^x和1不同余n的为合数. for(int i=1;i<=t;i++){ ret=multi_mod(ret,ret,n); if(ret==n-1)return false; //满足对所有的i=0,1,2,...,t-1.a^(2^i*x)和-1不同余n的为合数. // i=0时即使上面循环一开始的那个判定(ret==n-1) // 所以在素数判定中,这两个条件仅仅作为必要条件而不是充分条件! } /* if(ret==1)return false; else*/ return true; } bool Miller_Rabin(LL n){ if(n==2)return true; if(n<2||n%2==0)return false; LL x=n-1; LL t=0; while((x&1)==0){ x>>=1; t++; } //上面的步骤求得n-1=2^k*q,q是奇数. for(int i=0;i<S;i++){//随机大法,S越大,成功率越大.也可以使用底数组合(2,7,61)。 LL a=rand()%(n-1)+1; //1-n if(check(a,n,t))return false;//如果是合数,返回false; } return true; } LL gcd(LL a,LL b){ if(!b)return a; else return gcd(b,a%b); } LL Pollard_rho(LL x,LL c){ //函数f(x)=(x^2+c)%n LL i=1,k=2; LL x0=rand()%x; // x1为随机数. LL y=x0; while(1){ x0=(multi_mod(x0,x0,x)+c)%x; //x0即x2,y即x1. LL yx=y-x0; if(yx<0)yx*=-1; LL d=gcd(yx,x);// 求gcd的原因是存在更多的因数,而不是只知道p整除n,n=p*q.当求gcd(x,n)>1时则有p,2p,3p,4p... // 必须abs(y-x0).? if(d>1&&d<=x)return d; // if(d==x)return d,即if(y==x0)return x; if(++i==k)y=x0,k<<=1;//Brents’Algorithm?效率更加? } } void getpf(LL n){ if(Miller_Rabin(n)){ pfact[ant++]=n; return ; } LL p=n; while(p>=n){ p=Pollard_rho(p,rand()%(n-1)+1); } getpf(p); getpf(n/p); } int main(){ int T; LL n; scanf("%d",&T); while(T--){ scanf("%lld",&n); if(Miller_Rabin(n)){ printf("Primen"); continue; } ant=0; LL ans; getpf(n); ans=pfact[0]; for(int i=1;i<ant;i++) ans=min(ans,pfact[i]); printf("%lldn",ans); } } (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |