bzoj 3667: Rabin-Miller算法 (Miller_rabbin+Pollard rho)

3667: Rabin-Miller算法

Time Limit: 60 Sec   Memory Limit: 512 MB
Submit: 1278   Solved: 398
[ Submit][ Status][ Discuss]

Description

Input

第一行:CAS,代表数据组数(不大于350),以下CAS行,每行一个数字,保证在64位长整形范围内,并且没有负数。你需要对于每个数字:第一,检验是否是质数,是质数就输出Prime 
第二,如果不是质数,输出它最大的质因子是哪个。 

Output

第一行CAS(CAS<=350,代表测试数据的组数) 
以下CAS行:每行一个数字,保证是在64位长整形范围内的正数。 
对于每组测试数据:输出Prime,代表它是质数,或者输出它最大的质因子,代表它是和数 

Sample Input

6
2
13
134
8897
1234567654321
1000000000000

Sample Output

Prime
Prime
67
41
4649
5

HINT

数据范围: 

保证cas<=350,保证所有数字均在64位长整形范围内。 

Source

[ Submit][ Status][ Discuss]

题解:Miller_rabbin+Pollard rho

这道题时限卡的丧心病狂,不能用快速乘,否则会TLE

#include
#include
#include
#include
#include
#define LL long long 
using namespace std;
LL n,mx;
LL mul(LL a,LL b,LL p)
{
    /*LL ans=0; LL base=a%p;
    while (b) {
        if (b&1) ans=(ans+base)%p;
        b>>=1;
        base=(base+base)%p;
    }
    return ans;*/
    LL tmp=(a*b-(LL)((long double)a/p*b+1e-8)*p);
    return tmp<0?tmp+p:tmp;
}
LL quickpow(LL num,LL x,LL p)
{
    LL ans=1; LL base=num%p;
    while (x) {
        if (x&1) ans=mul(ans,base,p);
        x>>=1;
        base=mul(base,base,p);
    }
    return ans;
}
bool miller_rabbin(LL n)
{
    if (n==2) return true;
    if (n<=1||!(n&1)) return false;
    LL t=0,a,x,y,u=n-1;
    while (!(u&1)) t++,u>>=1;
    for (int i=0;i<=10;i++) {
        a=rand()*rand()%(n-1)+1;
        x=quickpow(a,u,n);
        for (int j=0;jx?y-x:x-y;
        p=gcd(n,p);
        if(i==k)y=x,k+=k;
    }
    return p;
}
void solve(LL n)
{
    if (n==1) return;
    if (miller_rabbin(n)) {
        mx=max(mx,n);
        return;
    }
    LL p=n; 
    while (p==n) p=pollard_rho(p,rand()%(n-1)+1);
    solve(p); solve(n/p);
}
int main()
{
    srand(2000001001);
    int T; scanf("%d",&T);
    while (T--) {
        scanf("%lld",&n);
        //cout<




你可能感兴趣的:(数论)