1. 程式人生 > >hihocoder 1287 : 數論一·Miller-Rabin質數測試 大質數判定

hihocoder 1287 : 數論一·Miller-Rabin質數測試 大質數判定

公鑰 queue 是否 iostream abi i+1 href 其中 興趣

時間限制:10000ms 單點時限:1000ms 內存限制:256MB

描述

小Hi和小Ho最近突然對密碼學產生了興趣,其中有個叫RSA的公鑰密碼算法。RSA算法的計算過程中,需要找一些很大的質數。

小Ho:要如何來找出足夠大的質數呢?

小Hi:我倒是有一個想法,我們可以先隨機一個特別大的初始奇數,然後檢查它是不是質數,如果不是就找比它大2的數,一直重復,直到找到一個質數為止。

小Ho:這樣好像可行,那我就這麽辦吧。

過了一會兒,小Ho拿來了一張寫滿數字的紙條。

小Ho:我用程序隨機生成了一些初始數字,但是要求解它們是不是質數太花時間了。

小Hi:你是怎麽做的啊?

說著小Hi接過了小Ho的紙條。

小Ho:比如說我要檢測數字n是不是質數吧,我就從2開始枚舉,一直到sqrt(n),看能否被n整除。

小Hi:那就對了。你看紙條上很多數字都是在15、16位左右,就算開方之後,也有7、8位的數字。對於這樣大一個數字的循環,顯然會很花費時間。

小Ho:那有什麽更快速的方法麽?

小Hi:當然有了,有一種叫做Miller-Rabin質數測試的算法,可以很快的判定一個大數是否是質數。

提示:Miller-Rabin質數測試

輸入

第1行:1個正整數t,表示數字的個數,10≤t≤50

第2..t+1行:每行1個正整數,第i+1行表示正整數a[i],2≤a[i]≤10^18

輸出

第1..t行:每行1個字符串,若a[i]為質數,第i行輸出"Yes",否則輸出"No"

樣例輸入
3
3
7
9
樣例輸出
Yes
Yes
No
裸模板題直接套模板
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <iomanip>
#include <math.h>
#include <map>
using namespace std;
#define FIN     freopen("input.txt","r",stdin);
#define FOUT    freopen("output.txt","w",stdout);
#define INFLL   0x3f3f3f3f3f3f3f
#define lson    l,m,rt<<1
#define rson    m+1,r,rt<<1|1
typedef long long LL;
typedef pair<int, int> PII;

LL multi(LL a, LL b, LL mod) {
    LL ret = 0;
    while(b) {
        if(b & 1) ret = ret + a;
        if(ret >= mod) ret -= mod;
        a = a + a;
        if(a >= mod) a -= mod;
        b >>= 1;
    }
    return ret;
}
LL power(LL a, LL b, LL mod) {
    LL ret = 1;
    while(b) {
        if(b & 1) ret = multi(ret, a, mod);
        a = multi(a, a, mod);
        b >>= 1;
    }
    return ret;
}
bool Miller_Rabin(LL n) {
    LL u = n - 1, pre, x;
    int i, j, k = 0;
    if(n == 2 || n == 3 || n == 5 || n == 7 || n == 11) return true;
    if(n == 1 || (!(n % 2)) || (!(n % 3)) || (!(n % 5)) || (!(n % 7)) || (!(n % 11))) return
            false;
    for(; !(u & 1); k++, u >>= 1);
    for(i = 0; i < 5; i++) {
        x = rand() % (n - 2) + 2;
        x = power(x, u, n);
        pre = x;
        for(j = 0; j < k; j++) {
            x = multi(x, x, n);
            if(x == 1 && pre != 1 && pre != (n - 1))
                return false;
            pre = x;
        }
        if(x != 1) return false;
    }
    return true;
}

int main() {
    LL a;
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%lld", &a);
        if(Miller_Rabin(a)) puts("Yes");
        else puts("No");

    }
    return 0;
}

  




hihocoder 1287 : 數論一·Miller-Rabin質數測試 大質數判定