zoukankan      html  css  js  c++  java
  • poj 1811 随机素数和大数分解(模板)

    Sample Input

    2
    5
    10
    

    Sample Output

    Prime
    2

    模板学习:

    判断是否是素数,数据很大,所以用miller,不是的话再用pollard rho分解

    miller : 通过费马小定理,若N为素数,a^(N-1) = 1 (mod N),

    再利用二次判定:

    若x为素数,0<x<p, x*x = 1(mod q)


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <time.h>
    #define N 10100
    typedef long long ll;
    using namespace std;
    
    const int S = 8;       //随机判定次数  一般8 - 10
    
    // a*b%c
    ll mult_mod(ll a,ll b,ll c)
    {
        a %= c;
        b %= c;
        ll ret = 0;
        ll temp = a;
        while(b)
        {
            if(b&1)
            {
                ret += temp;
                if(ret > c) ret -= c;
            }
            temp <<= 1;
            if(temp > c) temp -= c;
            b >>= 1;
        }
        return ret;
    
    }
    
    // (a^n)%mod
    ll pow_mod(ll a,ll n,ll mod)              
    {
        ll ret = 1;
        ll temp = a%mod;
        while(n)
        {
            if(n & 1)
                ret = mult_mod(ret,temp ,mod);
            temp = mult_mod(temp,temp,mod);
            n>>= 1;
        }
        return ret;
    }
    //通过费马小定理,a^(n-1)=1(mod n) ;来判断n是否是素数
    bool check(ll a,ll n,ll x,ll t)
    {
        ll ret = pow_mod(a,x,n);
        ll last = ret;
        for(int i = 1; i <= t; i++)
        {
            ret = mult_mod(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)            //随机素数
    {
        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++;
        };
        srand(time(NULL));       //G++时不要
    
        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 tol;
    
    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;
    }
    //找因子
    ll pollard_rho(ll x,ll c)
    {
        ll i = 1,k = 2;
        srand(time(NULL));
        ll x1 = rand()%(x-1)+1;
        ll y = x1;
        while(1)
        {
            i++;
            x1 = (mult_mod(x1,x1,x)+c)%x;
            ll d = gcd(y-x1,x);
            if(d!=1 && d!=x) return d;
            if(y == x1) return x;
            if(i == k)
            {
                y = x1;
                k += k;
            }
        }
    }
    //对n进行分解,存入数组,
    void findfac(ll n,int k)           //大数分解
    {
        if(n == 1)
            return ;
        if(miller_rabin(n))       //判素
        {
            factor[tol++] = n;
            return ;
        }
        ll p = n;
        int c = k;
        while( p>= n)
            p = pollard_rho(p,c--);     //防止死循环k,值变换
        findfac(p,k);
        findfac(n/p,k);
    
    }
    
    int main()
    {
        int t;
        ll n;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%I64d",&n);
            if(miller_rabin(n))  printf("Prime
    ");
            else
            {
                tol = 0;
                findfac(n,107);
                ll ans = factor[0];
                for(int i = 1; i < tol; i++)
                    ans = min(ans,factor[i]);
                printf("%I64d
    ",ans);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    剑指offer 整数中1出现的次数(从1到n整数中1出现的次数)
    剑指offer 把数组排成最小的数
    剑指offer 丑数
    剑指offer 字符串的排列
    剑指offer 数组中出现次数超过一半的数字
    剑指offer 最小的K个数
    操作系统 页面置换算法(C++实现)
    剑指offer 二叉搜索树与双向链表
    剑指offer 复杂链表的复制
    操作系统 银行家算法(C++实现)
  • 原文地址:https://www.cnblogs.com/Przz/p/5409788.html
Copyright © 2011-2022 走看看