[ACM]伪素数

Time Limit: 1000MS Memory Limit: 65536KB
Total Submissions: 81 Accepted: 9

Description:


Fermat's theorem states that for any prime number p and for any integer a > 1, a^p == 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 ≤ 1,000,000,000 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

Hint:


 

Source:


23 September, 2007 - Waterloo local contest

 

解题思路:

这题主要是考察素数的判定方法。首先要确保不是素数,然后还满足a^p==a mod p。

 

复制代码
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->#include <iostream>
#include 
<cstring>
#include 
<cstdlib>
#include 
<cstdio>
using namespace std;
typedef unsigned __int64 u64;
const int MAX = 100;
const int MAXN = 30;
u64 len, dig, limit;
u64 mod(u64 a, u64 b, u64 n) {
     
if(! a) return 0;
     
return (((a & dig) * b) % n + (mod(a >> len, b, n) << len) % n) % n;
}
u64 by(u64 a, u64 b, u64 n) {
      u64 p;
      p 
= 8, len = 61;
      
while(p < n) {
           p 
<<= 4;
           len 
-= 4;
      }
      dig 
= ((limit / p) << 1- 1;
      
return mod(a, b, n);
}
u64 random() {
      u64 a;
      a 
= rand();
      a 
*= rand();
      a 
*= rand();
      a 
*= rand();
      
return a;
}
u64 square_multiply(u64 x, u64 c, u64 n) {
      u64 z 
= 1;
      
while(c) {
           
if(c & 1) z = by(z, x, n);
           x 
= by(x, x, n);
           c 
>>= 1;
      }
      
return z;
}
bool Miller_Rabin(u64 n) {
      
if(n < 2return false;
      
if(n == 2return true;
      
if(! (n & 1)) return false;
      u64 i, j, k, m, a;
      m 
= n - 1;
      k 
= 0;
      
while(m % 2 == 0) {
           m 
>>= 1; k ++;
      }
      
for(i = 0; i < MAX; i ++) {
           a 
= square_multiply(random() % (n - 1+ 1, m, n);
           
if(a == 1continue;
           
for(j = 0; j < k; j ++) {
                
if(a == n - 1break;
                a 
= by(a, a, n);
           }
           
if(j < k) continue;
           
return false;
      }
      
return true;
}
int main() {
      u64 a, p;
      
while(scanf("%I64d %I64d"&p, &a) && (p || a)) {
           
if(Miller_Rabin(p)) {
                 printf(
"no ");
           }
else if(square_multiply(a, p, p) == a) {
                 printf(
"yes ");
           }
else {
                 printf(
"no ");
           }
      }
      
return(0);
}
复制代码

 

上面的代码中用到了Miller_Rabin素性检测算法,虽然是概率算法,但是在实际中还是够用的,如果用传统的确定性素数检测算法必然导致超时。

posted on   小橋流水  阅读(317)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述

导航

统计

点击右上角即可分享
微信分享提示