给出2个数,p和a,2<p<=1e9,1<a<p
若p满足下面2个条件,输出yes,否则输出no
1.p不是素数
2.有a^p=a(mod p)
先判断第一个条件:
本来想用一个数组is_prime[i]表示i是不是素数的,明显,这里p太大,数组开不下
若p不是素数的话,
则p必有p=b*c,其中b<=c,
则(sqrt(p))^2=b*c,则b<=sqrt(p)<=10^4.5<10^5
所以若在10^5内存在数b满足b<p&&p%b==0,说明p不是素数
进一步,只要验证10^5存在素数b1满足b1<p&&p%b1==0,说明p不是素数,即满足第一个条件
所以只要把10^5内的所有素数找出来,放在数组prime里面,对于p,遍历一边即可,注意:prime[i]>=p时,要break
若满足了第一个条件,验证第二个条件,快速幂即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 5 using namespace std; 6 7 #define LL long long 8 9 const int maxn=1e5; 10 bool is_prime[maxn]; 11 int prime[maxn>>1]; 12 13 int init_prime() 14 { 15 int i; 16 int tot=1; 17 int e=(int)(sqrt(0.0+maxn)+1); 18 memset(is_prime,true,sizeof is_prime); 19 is_prime[1]=false; 20 is_prime[2]=true; 21 prime[tot++]=2; 22 for(i=4;i<maxn;i+=2) 23 is_prime[i]=false; 24 for(i=3;i<e;i+=2) 25 { 26 if(is_prime[i]) 27 { 28 prime[tot++]=i; 29 int s; 30 for(int j=i*i,s=2*i;j<maxn;j+=s) 31 is_prime[j]=false; 32 } 33 } 34 for(;i<maxn;i+=2) 35 { 36 if(is_prime[i]) 37 prime[tot++]=i; 38 } 39 return tot; 40 } 41 42 LL quick_pow(LL a,LL p) 43 { 44 LL mod=p; 45 LL ret=1; 46 while(p>0) 47 { 48 if(p&1) 49 ret=ret*a%mod; 50 a=a*a%mod; 51 p>>=1; 52 } 53 return ret; 54 } 55 56 void solve(int tot,LL p,LL a) 57 { 58 bool flag=false; 59 for(int i=1;i<tot;i++) 60 { 61 if(prime[i]>=p) 62 break; 63 if(p%prime[i]==0) 64 { 65 flag=true; 66 break; 67 } 68 } 69 if(!flag) 70 { 71 printf("no "); 72 return ; 73 } 74 LL ret=quick_pow(a,p); 75 if(ret%p==a%p) 76 { 77 printf("yes "); 78 } 79 else 80 { 81 printf("no "); 82 } 83 return ; 84 } 85 86 int main() 87 { 88 LL p,a; 89 int tot=init_prime(); 90 while(scanf("%lld%lld",&p,&a)) 91 { 92 if(!p&&!a) 93 break; 94 solve(tot,p,a); 95 } 96 return 0; 97 }