【 POJ 3641 】Pseudoprime numbers

5 篇文章 0 订阅
1 篇文章 0 订阅

Pseudoprime numbers

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8702 Accepted: 3658
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

—————————————————————————————————————————————
题意:给伪素数一个定义,根据费马小定理ap = a (mod p)的非素数被称为伪素数,输入若干组a、p判断是不是伪素数,是输出yes,不是输出no。

一开始一直没看懂“ ap = a (mod p) ”这是什么玩意,后来用计算器凑了凑数据,估摸着是 (a^p)%p == a (因为p>a) ,后来试了一下,果然就是这样。

一个素数判断加一个快速幂,速度出代码。(一开始用了素数打表,后来激动地函数写完了回头看了一眼范围……默默的删掉重写)

最坑的是调用的时候一不小心把函数名掉了,结果找了半天。

上代码:

——————————————————————————————————————————————

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#define M 1000000000+10  //如果数量太多不适宜用素数打表,容易栈溢出 
using namespace std;

int isprime(long long n)  //用了类似于素数打表的技巧,优化一下
{  
    if(n == 2)  
        return 1;  
    if(n <= 1 || n%2 == 0)  
        return 0;  
    long long j = 3;  
    while( j <= (long long)sqrt(double(n)) )  
    {  
        if( n%j == 0 )  
            return 0;  
        j += 2;  
    }  
    return 1;  
}  

long long  pow( long long a1, long long b,long long mod)
{                    //一般快速幂
    long long r = 1,base = a1;
    while( b )
    {
        if( b&1 )  //位运算 b%2 == 1 
        {
            r = ( base*r )%mod; //取b为奇数的时候相乘
        }
        base = (base*base)%mod;
        b>>=1;  //  b/=2;
    }
        return r;
}
//简介快速幂: 
// (偶数) a^n=((a^2)^n/2)=((a^2)^2)^n/4)=(((a^2)^2)^2)^n/8)=.....
//(奇数)a^n=(((a^2)^n/2)*a)=......(把多余的a拿出来乘给r,相当于先储存进r中,其他的和偶数一样)
//最后b一定会有一次等于一,把储存进r的和没有存进r的相乘最后输出结果。
int main()
{
    long long ad,p,MOD;
    while( ~scanf("%lld%lld",&p,&ad) && !( ad==0 && p==0 ) )
    {
        if( isprime(p) )
        {
            printf("no\n"); 
            continue;
        }
        MOD=pow(ad,p,p);             //函数名不加,活该 WA 一辈子⊙﹏⊙ 
        if( ad == MOD )printf("yes\n");
        else printf("no\n"); 
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值