zoukankan      html  css  js  c++  java
  • Miller Rabin 随机性素数测试[模板]

    http://poj.org/problem?id=1811

    View Code
    /*=====================================================*\
    | Miller Rabin 判断一个大数是不是素数 | Pollard 找出因子
    \*=====================================================*/
    #define inf 0x3f3f3f3f
    #define linf inf*inf
    #define SS 8//Miller测试次数
    #define C 240
    typedef long long ll;
    ll N,ans;
    void swap(ll&x,ll&y) {x=x^y;y=x^y;x=x^y;}
    ll f_abs(ll x) {return (x)>(0)?(x):(-x);} 
    ll gcd(ll x,ll y) {return y?gcd(y,x%y):x;}
    
    ll mul_mod(ll x,ll y,ll z) {  //x*y%z
        ll res=0;  x%=z;
        while(y) {
            if(y&1) {
                res+=x;
                if(res>=z) res-=z;
            }
            x<<=1; y>>=1;
            if(x>=z) x-=z;
        }
        return res;
    }
    
    ll exp_mod(ll x,ll y,ll z) {  //(x^y)%z
        ll res=1;
        while(y) {
            if(y&1) res=mul_mod(res,x,z);
            x=mul_mod(x,x,z);  y>>=1;
        }
        return res;
    }
    
    bool Wintess(ll a,ll n) { //以x为基对n进行Miller测试并实现二次探测
        ll m=n-1,x,y,i,j=0;
        while(m%2==0) { m>>=1,j++; }
        x=exp_mod(a,m,n);
        for(i=1;i<=j;i++) {
            y=exp_mod(x,2,n);
            if((y==1) && (x!=1) && (x!=n-1)) return true;
            x=y;
        }
        if(y!=1) return true;
        else return false;
    }
    
    bool mill_rabin(ll s,ll n) { //对n进行s次的Miller测试
        ll a, i;
        if(n==1) return false;
        if(n==2) return true;
        if(n%2==0) return false;
        srand(time(NULL));
        for(i=0;i<s;i++) {
            a=rand()%(n-1)+1;
            if(Wintess(a,n)) return false;
        }
        return true;
    }
    ll Pollard(ll n,ll c) { //对n进行因字分解,找出n的一个因子,注意该因子不一定是最小的
        ll i,j,k,x,y,d;
        srand(time(NULL));
        i=1, k=2, x=rand()%n, y=x;
        while(1) {
            i++;
            x=(mul_mod(x,x,n)+c)%n;
            d=gcd(f_abs(y-x),n);
            if(d>1 && d<n) return d;
            if(y==x) return n; //该数已经出现过,直接返回即可
            if(i==k) { y=x; k<<=1; }
        }
    }
    void get_small(ll n,ll c) { //找出最小的素数因子
        ll m;
        if(n==1) return;
        if(mill_rabin(SS,n)) { //判断是否为素数
            if(n<ans) ans=n;
            return;
        }
        m=n;
        while(m==n) m=Pollard(n,c--); //找出n的一个因子
        get_small(m,c); get_small(n/m,c);
    }
    void get_data() {
        scanf("%lld",&N);
    }
    void solve() {
        if(mill_rabin(SS,N)) puts("Prime");
        else {
            ans=linf;
            get_small(N,C);
            printf("%lld\n",ans);
        }
    }
  • 相关阅读:
    纯前端导出Excel表格
    vue 组件按需引用,vue-router懒加载,vue打包优化,加载动画
    解决图片循环展示间距
    微信小程序aes前后端加密解密交互
    判断字符串中是否包含表情
    银行卡号Luhn校验算法
    身份证校验(支持15位和18位身份证号)、邮箱校验正则
    数组去重
    bootstrap 中 css 与 javascript 的使用
    js 分页
  • 原文地址:https://www.cnblogs.com/zhang1107/p/3065917.html
Copyright © 2011-2022 走看看