hdu 1905 poj3641素数判定与快速幂取余

还是比较简单的,看题目的数据范围,貌似简单判断素数的方法(复杂度sqrt(p))也能过,不过手上有素数测试的模板,就直接用了。秒杀。。。

/*

 * hdu1905/win.cpp

 * Created on: 2012-7-12

 * Author    : ben

 */

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

#include <stack>

#include <string>

#include <vector>

#include <deque>

#include <list>

#include <functional>

#include <numeric>

#include <cctype>

using namespace std;



typedef long long LL;



int modular_exp(int a, int b, int c) {

    LL res, temp;

    res = 1 % c, temp = a % c;

    while (b) {

        if (b & 1) {

            res = res * temp % c;

        }

        temp = temp * temp % c;

        b >>= 1;

    }

    return (int) res;

}



int witness(int a, int n) {

    LL x, d = 1,i = (LL)(ceil(log(n - 1.0) / log(2.0)) - 1);

    for (; i >= 0; i--) {

        x = d;

        d = (d * d) % n;

        if (d == 1 && x != 1 && x != n - 1)

            return 1;

        if (((n - 1) & (1 << i)) > 0)

            d = (d * a) % n;

    }

    return (d == 1 ? 0 : 1);

}



int miller_rabin(int n, int s = 50) {

    if (n == 2)

        return 1;

    if ((n % 2) == 0)

        return 0;

    int j;

    LL a;

    for (j = 0; j < s; j++) {

        // rand()随机产生[0, RAND_MAX)内的整数RAND_MAX=32768

        // 直接%n产生不了[RAND_MAX, n)之间的数,使用LL防止乘法溢出

        a = (LL)rand() * (n - 2) / RAND_MAX + 1;

        if (witness(a, n))

            return 0;

    }

    return 1;

}



int main() {

#ifndef ONLINE_JUDGE

    freopen("data.in", "r", stdin);

#endif

    int p, a;

    while(scanf("%d%d", &p, &a) == 2) {

        if(p == 0 && a == 0) {

            break;

        }

        if(miller_rabin(p)) {

            puts("no");

            continue;

        }

        if(modular_exp(a, p, p) == a) {

            puts("yes");

        }else {

            puts("no");

        }

    }

    return 0;

}

你可能感兴趣的:(poj)