1. 程式人生 > >大數素性測試+大數質因數分解(miller-rabin,Pollard_rho演算法)

大數素性測試+大數質因數分解(miller-rabin,Pollard_rho演算法)

<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="cpp">//不明白的地方:factor[]中不是素因數嗎,為何有2

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<iostream>
#include<algorithm>
using namespace std;


//****************************************************************
// Miller_Rabin 演算法進行素數測試
//速度快,而且可以判斷 <2^63的數
//****************************************************************
const int S=20;//隨機演算法判定次數,S越大,判錯概率越小


//計算 (a*b)%c.   a,b都是long long的數,直接相乘可能溢位的
//  a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
{
    a%=c;
    b%=c;
    long long ret=0;
    while(b)
    {
        if(b&1){ret+=a;ret%=c;}
        a<<=1;
        if(a>=c)a%=c;
        b>>=1;
    }
    return ret;
}



//計算  x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
{
    if(n==1)return x%mod;
    x%=mod;
    long long tmp=x;
    long long ret=1;
    while(n)
    {
        if(n&1) ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1;
    }
    return ret;
}





//以a為基,n-1=x*2^t      a^(n-1)=1(mod n)  驗證n是不是合數
//一定是合數返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
    long long ret=pow_mod(a,x,n);
    long long 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;
    return false;
}

// Miller_Rabin()演算法素數判定
//是素數返回true.(可能是偽素數,但概率極小)
//合數返回false;

bool Miller_Rabin(long long n)
{
    if(n<2)return false;
    if(n==2)return true;
    if((n&1)==0) return false;//偶數
    long long x=n-1;
    long long t=0;
    while((x&1)==0){x>>=1;t++;}
    for(int i=0;i<S;i++)
    {
        long long a=rand()%(n-1)+1;//rand()需要stdlib.h標頭檔案
        if(check(a,n,x,t))
            return false;//合數
    }
    return true;
}


//************************************************
//pollard_rho 演算法進行質因數分解
//************************************************
long long factor[100];//質因數分解結果(剛返回時是無序的)
int tol;//質因數的個數。陣列小標從0開始

long long gcd(long long a,long long b)
{
    if(a==0)return 1;//???????
    if(a<0) return gcd(-a,b);
    while(b)
    {
        long long t=a%b;
        a=b;
        b=t;
    }
    return a;
}

long long Pollard_rho(long long x,long long c)
{
    long long i=1,k=2;
    long long x0=rand()%x;
    long long y=x0;
    while(1)
    {
        i++;
        x0=(mult_mod(x0,x0,x)+c)%x;
        long long d=gcd(y-x0,x);
        if(d!=1&&d!=x) return d;
        if(y==x0) return x;
        if(i==k){y=x0;k+=k;}
    }
}
//對n進行素因子分解
void findfac(long long n)
{
    if(Miller_Rabin(n))//素數
    {
        factor[tol++]=n;
        return;
    }
    long long p=n;
    while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}

int main()
{
    //srand(time(NULL));//需要time.h標頭檔案//POJ上G++不能加這句話
    long long n;
    while(scanf("%I64d",&n)!=EOF)
    {
        tol=0;
        findfac(n);
        for(int i=0;i<tol;i++)printf("%I64d ",factor[i]);
        printf("\n");
        if(Miller_Rabin(n))printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

題目:http://acm.hdu.edu.cn/showproblem.php?pid=3864

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<iostream>
#include<algorithm>
using namespace std;


//****************************************************************
// Miller_Rabin 演算法進行素數測試
//速度快,而且可以判斷 <2^63的數
//****************************************************************
const int S=20;//隨機演算法判定次數,S越大,判錯概率越小


//計算 (a*b)%c.   a,b都是long long的數,直接相乘可能溢位的
//  a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
{
    a%=c;
    b%=c;
    long long ret=0;
    while(b)
    {
        if(b&1){ret+=a;ret%=c;}
        a<<=1;
        if(a>=c)a%=c;
        b>>=1;
    }
    return ret;
}



//計算  x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
{
    if(n==1)return x%mod;
    x%=mod;
    long long tmp=x;
    long long ret=1;
    while(n)
    {
        if(n&1) ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1;
    }
    return ret;
}





//以a為基,n-1=x*2^t      a^(n-1)=1(mod n)  驗證n是不是合數
//一定是合數返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
    long long ret=pow_mod(a,x,n);
    long long 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;
    return false;
}

// Miller_Rabin()演算法素數判定
//是素數返回true.(可能是偽素數,但概率極小)
//合數返回false;

bool Miller_Rabin(long long n)
{
    if(n<2)return false;
    if(n==2)return true;
    if((n&1)==0) return false;//偶數
    long long x=n-1;
    long long t=0;
    while((x&1)==0){x>>=1;t++;}
    for(int i=0;i<S;i++)
    {
        long long a=rand()%(n-1)+1;//rand()需要stdlib.h標頭檔案
        if(check(a,n,x,t))
            return false;//合數
    }
    return true;
}


//************************************************
//pollard_rho 演算法進行質因數分解
//************************************************
long long factor[100];//質因數分解結果(剛返回時是無序的)
int tol;//質因數的個數。陣列小標從0開始

long long gcd(long long a,long long b)
{
    if(a==0)return 1;//???????
    if(a<0) return gcd(-a,b);
    while(b)
    {
        long long t=a%b;
        a=b;
        b=t;
    }
    return a;
}

long long Pollard_rho(long long x,long long c)
{
    long long i=1,k=2;
    long long x0=rand()%x;
    long long y=x0;
    while(1)
    {
        i++;
        x0=(mult_mod(x0,x0,x)+c)%x;
        long long d=gcd(y-x0,x);
        if(d!=1&&d!=x) return d;
        if(y==x0) return x;
        if(i==k){y=x0;k+=k;}
    }
}
//對n進行素因子分解,並且儲存在factor[]中,且結果無需可以重複,(N的因子的定義:可以整除N,包括1,不包括N)但是
//此演算法求出的因子不包括1,且1和2兩個值需要特判!!!!!!!!!!記住是素因子,當然2不是
void findfac(long long n)
{
    if(Miller_Rabin(n))
    {
        factor[tol++]=n;
        return;
    }
    long long p=n;
    while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}

int main()
{
    //freopen("b:\\data.in.txt", "r", stdin);
    //srand(time(NULL));//需要time.h標頭檔案//POJ上G++不能加這句話
    long long n;
    while(scanf("%I64d",&n)!=EOF)
    {
        if(n == 1 || n == 2 || n == 3)
        {
            printf("is not a D_num\n");
            continue;
        }
        tol=0;      //初始化因子的數量為0
        findfac(n);         //進行質因數分解
        sort(factor, factor + tol);
        if(tol == 2)
        {
            if(factor[0] != factor[1])
                printf("%I64d %I64d %I64d\n", factor[0], factor[1], n);
            else
                printf("is not a D_num\n");
        }
        else
            if(tol == 3)
        {
            if(factor[0] == factor[1] && factor[1] == factor[2])
                printf("%I64d %I64d %I64d\n", factor[0], factor[0]*factor[0], n);
            else
                printf("is not a D_num\n");
        }
        else
            printf("is not a D_num\n");
    }
    return 0;
}


相關推薦

大數素性測試+大數質因數分解miller-rabinPollard_rho演算法

<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="cpp">//不明白的地方:factor[]中不是素因數嗎,為

質因數分解NOIP2012 普及組第一題

輸入 質數 line syntax tool 輸出格式 兩個 因數 toolbar 描述 已知正整數n是兩個不同的質數的乘積試求出較大的那個質數。 格式 輸入格式 輸入只有一行包含一個正整數n。 輸出格式 輸出只有一行包含一個正整數p, 即較大的那個質數。 樣例1 樣例輸入

面試題14:剪繩子動態規劃貪心演算法

一、題目: 一根長度為n的繩子,剪成m段,m,n都大於1,且都為整數,每段長度記為k[0],k[1]…,k[m].求k[0]*k[1]…*k[m]可能的最大乘積 1.1解法: 兩種不同的方法解決這個問題,先用常規的需要O(n²)時間和O(n)空間的動態規劃,接著用只需要O(1)的

[演算法]兩種字串匹配演算法索引法KMP演算法對比C語言實現

今天做了個一個簡單的字元對比程式,功能是實現從A串刪除包含B最多的字元的操作,比如A=“aaaaabbbbbbabababa” B=“aaccbaab”,應當刪除“aab”的,不是aa,相信知道搜尋引擎的朋友肯定是知道的吧,這種演算法主要用於去除頁面中無效的關鍵字,來減少收錄的計算消耗的一種方法,好了,具體演

hdu 1150 Machine Schedule二分匹配匈牙利演算法

As we all know, machine scheduling is a very classical problem in computer science and has been studied for a very long history. Scheduling problems differ

Miller-Rabin大數素性測試

素性測試是檢驗一個給定的整數是否為質數的測試。 對於確定型演算法試除法,即嘗試從2到√N的整數是否整除N,若N較大,則演算法無法在如今大多數機器上一個可以忍耐的時間內結給出結果。使用隨機化演算法Miller-Rabin素性測試 則可以在極短的時間內得到一個較準

素數與素性測試Miller-Rabin測試(目前為止我見過最好的部落格

素數的個數無限多(不存在最大的素數) 存在任意長的一段連續數,其中的所有數都是合數(相鄰素數之間的間隔任意大) 所有大於2的素數都可以唯一地表示成兩個平方數之差。 當n為大於2的整數時,2n+1和2n-1兩個數中,如果其中一個數是素數,那麼另

米勒羅賓素性測試MillerRabin primality test

如何判斷一個素是素數 效率很高的篩法 打個表 (素數的倍數一定是合數) 就可以解決問題。 篩選法的效率很高,但是遇到大素數就無能為力了。 米勒羅賓素性測試是一個相當著名的判斷是否是素數的演算法 核心為

素數費馬!米勒—拉賓 素性測試MillerRabin primality test

chapter 1 Fermat's little theorem  費馬小定理 費馬小定理說的是:如果p是一個素數,那麼對於任意一個整數a,a p − a 能被p整除,也可以用模運算表示如下: (p是素數,a是整數) 這個定理又如下變式:如果p是一個素數,且整數a與p互素,那麼 a p−1 

LightOJ 1356 Prime Independence質因數分解+最大獨立集+Hopcroft-Carp

target pri 建圖 spa dfs cto rim %d 最大獨立集 http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1356 題意: 給出n個數,問最多能選幾個數,

[學習筆記] 素數測試質因數分解 - 學習筆記

copy了luogu上目前rk1的板子 分解質因數其中有一段還不知道在幹嘛: 列舉k是大於等於2的2的冪,每次初始化 x 0

大數據學習的思維原理機器懂人原理篇

bsp .com 最大 工作 什麽 http 發揮 style 裏程碑 我們在上一篇文章中給大家介紹了很多大數據學習的思維原理,對於這些思維原理都是需要大家掌握的,在這篇文章中我們給大家講解一下機器懂人原理,希望這篇文章能夠給大家帶來幫助。 首先我們給大家說說什麽是機器懂

luogu1075 質因數分解NOIP2012普及組第1題

時空限制    1000ms/128MB 題目描述 已知正整數n是兩個不同的質數的乘積,試求出兩者中較大的那個質數。 輸入輸出格式 輸入格式: 輸入只有一行,包含一個正整數n。 輸出格式

前端自動化測試之UI RECORDER二、PC錄制

啟動服務 域名 run ports shadow 科學 兼容 webp htm PC錄制教程 準備工作: NodeJs環境 請自行先安裝好nodejs環境,在命令行執行node -v命令成功說明已經安裝成功 Chrome瀏覽器 JAVA環境 UI Recorder We

閒扯測試工程師之發展覺得不錯拿來與大家分享

一,測試工程師的歷史 我算是接觸網際網路測試工作比較早的一批人了,在2010年研二實習的時候就開始在一家加拿大的企業做測試開發工程師了。2012年畢業的時候,貌似網際網路行業開始有專職的測試人員,而且不少中小型公司還沒有專職的測試人員,程式的質量由開發人員保證,產品進行簡單

素數判定的一些討論Miller-Rabin演算法

很久沒有寫部落格了。。。最近軍訓加開學,感覺刷題速度有降低,要補一補。 迴歸正題,正式進入數論階段,討論一下關於素數判定的那些事。 一類問題: 判定一個整數n(n>1)是否為素數。 演算法1: 直接根據素數的定義列舉i從2到(n−1),

手機APP專案測試點(內容)總結轉自趙大喬

對於手機專案(應用軟體),主要是進行系統測試。 而針對手機應用軟體的系統測試,我們通常從如下幾個角度開展測試工作: 功能模組測試  交叉事件測試  效能測試  安全測試  容量測試  相容性測試  介面測試  易用性/使用者體驗測試  硬體環境測試  安裝/解除安裝測試 

【Unity】ios平臺IAP內購和沙箱測試流程詳解開發中遇到的坑

Unity iOS內購 內購流程 1、在 AppStore 中建立相應的物品,建立內購沙盒測試賬號2、客戶端從後臺獲取相應的物品 ID (當然也可以再客戶端寫死,但後期擴充套件性就受限制了)3、依據相應的物品 ID 請求商品的相關資訊4、依據商品資訊建立訂單請求交易5

手把手教你搭建Pytest+Allure2.X環境詳細教程生成讓你一見鍾情的測試報告非常詳細非常實用

簡介  巨集哥之前在做介面自動化的時候,用的測試報告是HTMLTestRunner,雖說自定義模板後能滿足基本訴求,但是仍顯得不夠檔次,高階,大氣,遂想用其他優秀的report框架替換之。一次偶然的機會,在一個QQ群裡看到Allure的測試報告,真的是一見鍾情,特別的喜歡。但是由於時間的原因就沒有