POJ1811 大质数判断+质因数分解

解决本题基于以下两步:
—>1.素数判定(Miller-Rho)

由费马小定理 a^(p-1) % p=1 (其中p为质数) 可以随机取一个a,计算上式的结果是否为1而判断p是否为素数。
值得注意的是,通过上述方法正确率只有50%,解决方法是选择20个不同 的a只要有一个不满足上式,则可以判定p不是质数。

—>2.分解质因数(Pollar-Rho)

随机选取1<x,y<n,判断t=gcd(|x-y|,n)是否为1:
若不是则t为n的一个因数,递归分解t,n/t,并判断是否已分解为质数(经过实践与理论证明|x-y|比x更不容易与n互质^_^);
若互质,x=(x^2+c)%n,可以知道一段时间后x必定会出现循环节,那么用y来判断x是否已经重复,k每次<<1来枚举循环节的长度。
如果出现了循环的话,则更换c值,重新随机选取x。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
LL mult(LL a,LL b,LL n){
    LL ret=0;
    while(b){
        if(b&1LL) ret=(ret+a)%n;
        a=(a+a)%n;
        b>>=1;
    }
    return ret;
}
LL pow(LL a,LL u,LL n){
    LL ret=1;
    while(u){
        if(u&1LL) ret=mult(ret,a,n);
        a=mult(a,a,n);
        u>>=1;
    }
    return ret;
}
LL gcd(LL a,LL b){
    if(b==0) return a;
    return gcd(b,a%b);
}
LL x[100];
bool isprime(LL n){
    if(n==2) return true;
    int t=0,cnt=20;
    LL u=n-1;
    while(!(u&1)){
        t++;
        u>>=1;
    }
    while(cnt--){
        LL a=rand()%(n-2)+2;
        x[0]=pow(a,u,n);
        for(LL i=1;i<=t;i++){
            x[i]=mult(x[i-1],x[i-1],n);
            if(x[i]==1 && x[i-1]!=1 && x[i-1]!=n-1) return false;
        }
        if(x[t]!=1) return false;
    }
    return true;
}
LL devision(LL n,int c){
    LL i=1;
    LL x=rand()%(n-1)+1;
    LL y=x;
    LL k=2;
    while(1){
        i++;
        x=(mult(x,x,n)+c)%n;
        LL tmp=gcd((y-x+n)%n,n);
        if(tmp!=1 && tmp!=n) return tmp;
        if(x==y) return n;
        if(i==k){
            y=x;
            k<<=1;
        }
    }
}
LL ans;
void find(LL n,int c){
    if(n==1) return;
    if(isprime(n)){
        ans=min(ans,n);
        return;
    }
    LL p=n,k=c;
    while(p==n) p=devision(p,c--);
    find(p,k);
    find(n/p,k);
}
int main(){
    LL n,i;
    int t;
    scanf("%d",&t);
    while(t--){
        ans=1LL<<62;
        scanf("%lld",&n);
        find(n,120);
        if(ans==n) printf("Prime\n");
        else printf("%lld\n",ans);
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值