快速幂运算
模运算
素数判定
题意
判定一个数p是否为伪素数。
如果一个非素数 p 对任何 a > 1 满足 a^p = a (mod p),则称p是伪素数。
题解
- 用快速幂运算求a^p % p ,如果结果等于p并且p不是素数,则p是伪素数。
- 由于值很小,可以用下面两种方法判定。 (1)若小于根号p的素数里没有能整除p的,则p是素数
。(2)使用Miller_Rabin随机算法进行判定
代码
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
LL a,p;
bool isprime(LL n)
{
if(n == 2)
return true;
if(n % 2 == 0 || n <= 1)
return false;
LL sqrtn = (LL)sqrt((double)n);
for(LL j = 3; j < sqrtn; j += 2)
{
if(n % j ==0)
return false;
}
return true;
}
//****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
const int S=20;//随机算法判定次数,S越大,判错概率越小
//计算 (a*b)%c. a,b都是long long的数,直接相乘可能溢出的
// a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
{
a%=c;
b%=c;
long long ret=0;
while(b)
{
if(b&1){ret+=a;ret%=c;}
a<<=1;
if(a>=c)a%=c;
b>>=1;
}
return ret;
}
//计算 x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
{
if(n==1)return x%mod;
x%=mod;
long long tmp=x;
long long ret=1;
while(n)
{
if(n&1) ret=mult_mod(ret,tmp,mod);
tmp=mult_mod(tmp,tmp,mod);
n>>=1;
}
return ret;
}
//以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
//一定是合数返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
long long ret=pow_mod(a,x,n);
long long last=ret;
for(int i=1;i<=t;i++)
{
ret=mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1) return true;//合数
last=ret;
}
if(ret!=1) return true;
return false;
}
// Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false;
bool Miller_Rabin(long long n)
{
if(n<2)return false;
if(n==2)return true;
if((n&1)==0) return false;//偶数
long long x=n-1;
long long t=0;
while((x&1)==0){x>>=1;t++;}
for(int i=0;i<S;i++) //
{
long long a=rand()%(n-1)+1;//rand()需要stdlib.h头文件
if(check(a,n,x,t))
return false;//合数
}
return true;
}
int main()
{
while(cin >> p >> a && p != 0 && a != 0)
{
//if(pow_mod(a, p, p) == a && !isprime(p)) //简单的对小的数进行素数判定
if(pow_mod(a, p, p) == a && !Miller_Rabin(p)) //用Miller_Rabin算法判定素数
cout<< "yes"<< endl;
else
cout << "no" << endl;
}
return 0;
}