Miller-Rabin&&Pollard-pho模板(板子总结)

思路来源

K Upside down primes German Collegiate Programming Contest 2015 [ Miller_Rabin ]-CSDN博客

https://www.cnblogs.com/mrclr/p/10259874.html

Miller-Rabin

如果WA,可以在不TLE情况下,适当加T的次数

还有个O(1)的快速乘的方法

ll mul(ll u,ll v,ll p)
{
return (u*v-ll((long double)u*v/p)*p+p)%p;
}
#include <stdio.h>
#include <iostream>
using namespace std;
 
typedef long long  ll;
const int T = 9;

ll mod_mult(ll a, ll b, ll mod) {           //大数乘法取模
    a %= mod;
    b %= mod;
    ll ans = 0;
    while (b) {
        if (b & 1) {
            ans += a;
            if (ans >= mod)
                ans -= mod;
        }
        a <<= 1;
        if (a >= mod) a = a - mod;
        b >>= 1;
    }
    return ans;
}
 
ll mod_pow(ll x, ll n, ll mod) {            //快速幂
    if (n == 0) return 1;
    ll res = mod_pow(mod_mult(x , x , mod), n / 2, mod);
    if (n & 1) res = mod_mult(res , x , mod);
    return res;
}
 
 
bool check(ll a, ll n, ll x, ll t) {       //来判断是不是素数
    ll ret = mod_pow(a, x, n), last = ret;
    for (int i = 1; i <= t; i ++) {
        ret = mod_mult(ret, ret, n);
        if (ret == 1 && last != 1 && last != n - 1) return true;//合数
        last = ret;
    }
    if (ret != 1) return true;
    else return false;
}
 
bool Miller_Rabin(ll n)         //Miller_Rabin算法
{
    if( n < 2) return false;
    if( n == 2) return true;
    if(!(n & 1)) return false;//偶数
    ll x = n - 1, t = 0;
    while (!(x & 1)) { x >>= 1; t++;}
    for (int i = 0; i < T; i ++) {
        ll a = rand() % (n - 1) + 1;
        if (check(a, n, x, t))
            return false;
    }
    return true;
}

Pollard-pho

2023.10.7 板子替换为洛谷板子,可通过【模板】Pollard-Rho - 洛谷

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
typedef __int128 LL;
typedef double db;

inline ll read(){
    ll ans = 0;
    char ch = getchar(), last = ' ';
    while(!isdigit(ch)) {last = ch; ch = getchar();}
    while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - '0'; ch = getchar();}
    if(last == '-') ans = -ans;
    return ans;
}

ll ksm(ll a,ll b,ll mod) {
    ll ans=1;
    for(;b;a=(LL)a*a%mod,b/=2) {
        if(b&1) ans=(LL)ans*a%mod;
    }
    return ans;
}
inline ll mul(ll x,ll y,ll Mod){
    ll r=x*y-Mod*(ll)(1.L/Mod*x*y);
    return r-Mod*(r>=Mod)+Mod*(r<0);
}

namespace MR{
    const ll pr[7]={2,325,9375,28178,450775,9780504,1795265022};
    inline bool isprime(ll x){
        if(x<3||x%2==0)return x==2;
        int r=0;
        ll k=x-1;
        for(;!(k&1);k>>=1,++r);
        for(int T=7,j;T--;){
            ll p=pr[T];
            if(p%x==0)continue;
            ll v=ksm(p,k,x);
            if(v==1)continue;
            for(j=1;j<=r;++j,v=mul(v,v,x))
                if(v==x-1)break;
            if(j>r)return 0;
        }
        return 1;
    }
}
namespace PR{
    vector<ll>ans;
    inline ll calc(ll n){
        if(!(n&1))return 2;
        ll x=0,y=0,z=0,p=1,q,g;
        for(int i=0;(i&255)||(g=__gcd(p,n))==1;\
            ++i,x=mul(x,x,n)+1,y=mul(y,y,n)+1,y=mul(y,y,n)+1){
            if(x==y)x=z++,y=mul(x,x,n)+1;
            q=mul(p,x-y+n,n);
            if(q)p=q;
        }
        return g;
    }
    inline void split(ll n){
        if(n==1)return;
        if(MR::isprime(n)){
            ans.push_back(n);
            return;
        }
        ll d=calc(n);
        while(d==1||d==n)d=calc(n);
        split(d),split(n/d);
    }
}
using namespace MR;
using namespace PR;

int main(){
    //freopen("poll.out","w",stdout);
    srand(time(0));
    int T = read();
    while(T--){
        ll n = read();
        ans.clear();
        split(n);
        int sz=ans.size();
        if(sz==1)puts("Prime");
        else printf("%lld\n",*max_element(ans.begin(),ans.end()));
    }
    return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值