POJ1811 Prime Test(Miller_Rabin素性测试+Pollard_rho质因子分解模板)

Prime Test

Given a big integer number, you are required to find out whether it's a prime number. 

Input
The first line contains the number of test cases T (1 <= T <= 20 ), then the following T lines each contains an integer number N (2 <= N < 2 54).
Output
For each test case, if N is a prime number, output a line containing the word “Prime”, otherwise, output a line containing the smallest prime factor of N.
Sample Input

2
5
10

Sample Output

Prime
2
题意:

题目很裸就是让判断素数是素数输出Prime不是素数的输出最小素因子

分析:

直接套用kuangbin模板

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long ll;
const int S = 8;
ll mul_mod(ll a,ll b,ll c){
    a %= c;
    b %= c;
    ll ret = 0;
    ll tmp = a;
    while(b){
        if(b & 1){
            ret += tmp;
            if(ret > c) ret -= c;
        }
        tmp <<= 1;
        if(tmp > c) tmp -= c;
        b >>= 1;
    }
    return ret;
}

ll q_pow(ll a,ll b,ll mod){
    ll ret = 1;
    ll tmp = a % mod;
    while(b){
        if(b & 1) ret = mul_mod(ret,tmp,mod);
        tmp = mul_mod(tmp,tmp,mod);
        b >>= 1;
    }
    return ret;
}

bool check(ll a,ll n,ll x,ll t){
    ll ret = q_pow(a,x,n);
    ll last = ret;
    for(int i = 1; i <= t; i++){
        ret = mul_mod(ret,ret,n);
        if(ret == 1 && last != 1 && last != n - 1) return true;
        last = ret;
    }
    if(ret != 1) return true;
    return false;
}

bool Miller_Rabin(ll n){
    if(n < 2) return false;
    if(n == 2) return true;
    if((n & 1) == 0) return false;
    ll x = n - 1;
    ll t = 0;
    while((x & 1) == 0){
        x >>= 1;
        t++;
    }
    for(int i = 0; i < S; i++){
        ll a = rand() % (n - 1) + 1;
        if(check(a,n,x,t))
            return false;
    }
    return true;
}

ll factor[100];
int tot;

ll gcd(ll a,ll b){
    ll t;
    while(b){
        t = a;
        a = b;
        b = t % b;
    }
    if(a >= 0) return a;
    else return -a;
}
//注意!!!!用迭代写gcd比用递归写省时间,用递归的超时了
ll pollard_rho(ll x,ll c){
    ll i = 1, k = 2;
    ll x0 = rand() % (x - 1) + 1;
    ll y = x0;
    while(1){
        i++;
        x0 = (mul_mod(x0,x0,x) + c) % x;
        ll d = gcd(y-x0,x);
        if(d != 1 && d != x) return d;
        if(y == x0) return x;
        if(i == k){
            y = x0;
            k += k;
        }
    }
}

void findfac(ll n,int k){
    if(n == 1) return;
    if(Miller_Rabin(n)){
        factor[tot++] = n;
        return;
    }
    ll p = n;
    int c = k;
    while(p >= n){
        p = pollard_rho(p,c--);
    }
    findfac(p,k);
    findfac(n/p,k);
}
int main(){
    int T;
    ll n;
    scanf("%d",&T);
    while(T--){
        scanf("%lld",&n);
        if(Miller_Rabin(n)) printf("Prime\n");
        else{
            tot = 0;
            findfac(n,107);
            ll ans = factor[0];
            for(int i = 1; i < tot; i++){
                ans = min(ans,factor[i]);
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值