• pojPseudoprime 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-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,当满足p不是素数且pow(a,p)%p==a时输出yes,否则输出no
    思路:只要会最基本的快速幂就可以做出这道题来。
    快速幂:思路就是将pow(a,p)中的p换成多个2的倍数相加的形式,那么pow(a,p)=pow(a,c1)*pow(a,c2)*....*pow(a,cn),其中p=c1+c2+..+cn;利用位运算符
    可以很容易实现这种操作。

    int Fastpow(int a,int p){

    int Fastpow(int a,int p){
    long long int base=a;
    long long int res=1;
    while(p){
    if(p&1) //若p的二进制表示形式最后一位数是1,则为真,否则为假
    res*=base/*,res=res%mod*/;
    base*=base;
    /*base=base%mod;*/
    p>>1; //将p的二进制表示形式后移一位,把刚处理过的p的最后一位去掉
    }
    return res;
    }

    快速幂的第二种表达方式就是利用递归

    int Fastpow(int a,int p){
    if(p==1) return a;
    long long int temp=Fastpow(a,p/2)%p;
    if(p%2==1) return temp*temp%p*a%p; //这里的第一个p若是省略,则会wrong answer
    else return temp*temp%p;
    }

    最后附上AC代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long int p;
    int Fastpow(int a,int n){
    long long int m=n,base=a;
    long long int res=1;
    while(m){
    if(m&1){
    res=res*base%p;
    }
    base=(base*base)%p;
    m>>=1;
    }
    return res;
    }
    /*int Fastpow(int a,int n){
    if(n==1) return a;
    long long int temp=Fastpow(a,n/2)%p;
    if(n%2==1) return temp*temp%p*a%p;
    else return temp*temp%p;
    }*/
    int main(){
    long long int a,c[100000];
    while(~scanf("%lld%lld",&p,&a)){
    if(p==0&&a==0) return 0;
    int plug=0;
    for(int i=2;i*i<=p;i++)
    if(p%i==0) plug=1;
    if(plug==0) {
    printf("no ");
    continue;
    }
    //cout<<Fastpow(a,p)<<endl;
    if(Fastpow(a,p)==a) printf("yes ");
    else printf("no ");
    }
    }

    这个是最基本的判断是否是素数,利用的是试除法,下面给出一个利用素数筛的快捷算法,比上面这一个耗时少不少:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn=31700;
    const long long int maxn1=1e9+10;
    int Fastpow(int a,int p){
    long long int m=p,base=a;
    long long int res=1;
    while(m){
    if(m&1){
    res=res*base%p;
    }
    base=(base*base)%p;
    m>>=1;
    }
    return res;
    }
    int main(){
    long long int p,a;
    int c[maxn],prim[maxn],j=0;
    memset(c,0,sizeof(c));
    for(int i=2;i*i<maxn1;i++){
    if(c[i]==0){
    prim[j]=i,j++;
    for(int k=i*i;k<maxn;k+=i)
    c[k]=-1;
    }
    }
    while(~scanf("%lld%lld",&p,&a)){
    if(p==0&&a==0) return 0;
    int plug=1;
    for(int i=0;i<j&&prim[i]<p;i++)
    if(p%prim[i]==0) plug=0;
    if(plug==1) {
    printf("no ");
    continue;
    }
    if(Fastpow(a,p)==a) printf("yes ");
    else printf("no ");
    }
    }


    作者:孙建钊
    出处:http://www.cnblogs.com/sunjianzhao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    hdu6354 杭电第五场 Everything Has Changed 计算几何
    hdu6351 Beautiful Now 杭电第五场 暴力枚举
    牛客多校第六场 J Heritage of skywalkert 随即互质概率 nth_element(求最大多少项模板)
    百度之星资格赛 调查问卷 bitset模板(直接将字符串转化成二进制数组并可以计算出十进制值)
    百度之星资格赛 子串查询 线段树
    牛客多校第五场 F take 期望转化成单独事件概率(模板) 树状数组
    牛客多校第五场 E room 二分图匹配 KM算法模板
    牛客第五场多校 J plan 思维
    idhttp提交post
    centos6.2 shutdown now关机进入单用户模式
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/11461512.html
Copyright © 2020-2023  润新知