POJ 3641 HDU 1905 Pseudoprime numbers 素数 模取幂

本文介绍了一种快速模取幂算法,并结合素数筛选技术实现对大数的素性判断。通过优化的算法提高了处理速度,在解决特定数学问题时更为高效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
---------------------------------------------------
    status : a312745658	3641	Accepted	328K
            16MS	C++	1732B	2012-05-18 21:36:37

    stratege : 快速模取幂,素数筛选, 判断一个大数是否为素数
    URL:  http://poj.org/problem?id=3641
           http://acm.hdu.edu.cn/showproblem.php?pid=1905
---------------------------------------------------
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std ;

typedef long long LL ;

LL p, c ;
LL res ;

const int MAXN = 40000 ;
int isPrime [MAXN] ;
bool flag ;
LL prime[MAXN] ;
int priLen;

void getPrime ()  // 筛选40000内的素数
{
    int i, j ;

    memset (isPrime, 0, sizeof(isPrime)) ;
    isPrime[1] = 1 ;
    priLen = 1 ;
    for (i = 4; i < MAXN; i += 2)
        isPrime[i] = 1 ;
    prime[0] = 2 ;
    for (i = 3; i < MAXN; i ++)
    {
        if (!isPrime[i])
        {
            int tmp = 2 * i ;
            prime[priLen ++] = i ;
            while (tmp < MAXN)
            {
                isPrime[tmp] = 1 ;
                tmp += i ;
            }
        }
    }
}

void ModPow(LL a, LL b, LL n) //在指数p不是素数的情况下,进行快速模取幂
{
    LL rec=1;
    while(b)
    {
        if (b & 1)
            rec = ((rec % n) * a) % n;
        a = ((a % n) * a) % n;
        b >>= 1;
    }
    res = rec % n;
}

bool judge (int x)  //判断指数是否为素数
{
    if (x < 40000)  //小于40000直接判断
    {
        if (!isPrime[x])
            return false ;
        return true ;
    }
    else
    {
        for (int i = 0; i <= priLen && prime[i]*prime[i] <= x; i ++)
        {
            if (x % prime[i] == 0) //大于40000,用来除以40000以内素数
                return true ;
        }
        return false ;  //40000内的素数都除不了,肯定是素数
    }
}


int main ()
{
    getPrime () ;
    while (scanf ("%d%d", &p, &c), p | c)
    {
        flag = true ;
        flag = judge (p) ;
        if (!flag)
        {
            printf ("no\n") ;
            continue ;
        }

        ModPow (c, p, p) ;// 快速模取幂
        if (res == c)   // res == (a^p) % p
            printf ("yes\n") ;
        else
            printf ("no\n") ;
    }
    return 0 ;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值