加入收藏 | 设为首页 | 会员中心 | 我要投稿 东莞站长网 (https://www.0769zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

大素数测试和大数素因子分解

发布时间:2021-02-27 17:13:49 所属栏目:大数据 来源:网络整理
导读:小黄书第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);
  }
}

(编辑:东莞站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!