hihoCoder 九十二周 数论一·Miller-Rabin质数测试 (数论 筛素数)

题目:http://hihocoder.com/contest/hiho92/problem/1

代码:

#include"stdio.h"
#include"stdlib.h"
#include"math.h"
#include"time.h"

long long mod_mul(long long a, long long b, long long  n)
{
    long long res = 0;
    while(b)
    {
        if(b&1)    res = (res + a) % n;
        a = (a + a) % n;
        b >>= 1;
    }
    return res;
}

long long mod_exp(long long a, long long b, long long n)
{
    long long res = 1;
    while(b)
    {
        if(b&1)    res = mod_mul(res, a, n);
        a = mod_mul(a, a, n);
        b >>= 1;
    }
    return res;
}

int miller_rabin(long long n)
{
    if(n == 2 || n == 3 || n == 5 || n == 7 || n == 11)    return 1;
    if(n == 1 || !(n%2) || !(n%3) || !(n%5) || !(n%7) || !(n%11))    return 0;

    long long x, pre, u;
    int i, j, k = 0;
    u = n - 1;    //要求x^u % n

    while(!(u%2==1))      //如果u为偶数则u右移,用k记录移位数
    {
        k++;
        u =u/2;
    }

    srand((long long)time(0));
    for(i = 0; i < 1; ++i)      //进行S次测试
    {
        x = rand()%(n-2) + 2;    //在[2, n)中取随机数
        if((x%n) == 0)    continue;

        x = mod_exp(x, u, n);    //先计算(x^u) % n,
        pre = x;
        for(j = 0; j < k; ++j)      //把移位减掉的量补上,并在这地方加上二次探测
        {
            x = mod_mul(x, x, n);
            if(x == 1 && pre != 1 && pre != n-1)    return 0;    //二次探测定理,这里如果x = 1则pre 必须等于 1,或则 n-1否则可以判断不是素数
            pre = x;
        }
        
        if(x != 1)    return 0;    //费马小定理
    }
    return 1;
}


int main()
{
    /*费马小定理的应用*/
    int i,n;
    long long a[50];

    scanf("%d",&n);

    for(i=0; i<n; i++)
    {
        scanf("%lld",&a[i]);
    }
    for(i=0; i<n; i++)
    {
        if(miller_rabin(a[i]))
            printf("Yes\n");
        else
            printf("No\n");
    }

}

有详细分析,在题目里。

你可能感兴趣的:(hihoCoder 九十二周 数论一·Miller-Rabin质数测试 (数论 筛素数))