poj3641Pseudoprime numbers(快速幂+同余定理)

本文介绍了一种快速判断特定数值是否为基于a的伪素数的方法,利用快速幂算法和同余定理,有效地解决了POJ3641题目中的问题。

poj3641Pseudoprime numbers

Description

Fermat's theorem states that for any prime number p and for any integer a > 1, ap = a (mod p). That is, if we raise a to the pth power and divide by p, the remainder is a. Some (but not very many) non-prime values of p, known as base-a pseudoprimes, have this property for some a. (And some, known as Carmichael Numbers, are base-a pseudoprimes for all a.)

Given 2 < p ≤ 1000000000 and 1 < a < p, determine whether or not p is a base-a pseudoprime.

Input

Input contains several test cases followed by a line containing "0 0". Each test case consists of a line containing p and a.

Output

For each test case, output "yes" if p is a base-a pseudoprime; otherwise output "no".

Sample Input

3 2
10 3
341 2
341 3
1105 2
1105 3
0 0

Sample Output

no
no
yes
no
yes
yes
题意:给你两个数p和a,如果a的p次方对p取余等于a并且p不是素数,输出yes,否则输出no。

解题思路:因为P比较大暴力的话肯定不行,这里用到了快速幂的算法和同余定理。

快速幂算法:可以把b按二进制展开为:b = p(n)*2^n  +  p(n-1)*2^(n-1)  +…+   p(1)*2  +  p(0)
其中p(i) (0<=i<=n)为 0 或 1

这样 a^b =  a^ (p(n)*2^n  +  p(n-1)*2^(n-1)  +...+  p(1)*2  +  p(0))
               =  a^(p(n)*2^n)  *  a^(p(n-1)*2^(n-1))  *...*  a^(p(1)*2)  *  a^p(0)
对于p(i)=0的情况, a^(p(i) * 2^(i-1) ) =  a^0  =  1,不用处理
我们要考虑的仅仅是p(i)=1的情况
化简:a^(2^i)  = a^(2^(i-1)  * 2) = (  a^(  p(i)  *  2^(i-1)  )  )^2。

同余定理:a*b%c=((a%c)*b)%c。

#include
  
   
#include
   
    
using namespace std;
int isprime(long n){
	int i;
	for(i=2;i*i
    
     =n){
		return 1;
	}
	else{
		return 0;
	}
}
int quickpow(long long n,long long m,long long mod)
{  
    long long ans=1,base=n;  
    while(m)  
    {  
        if(m&1) 
  
        {  
            ans=(base*ans)%mod; 
        }  
        base=(base*base)%mod;  
        m/=2;
    }  
    return ans;  
}  
int main(){
	long long p,a,mod;
	while(scanf("%lld %lld",&p,&a)&&p||a){
		
		if(isprime(p)==0&&quickpow(a,p,p)==a){
			printf("yes\n");
		}
		else{
			printf("no\n");
		}
	}
} 
    
   
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值