POJ 3641 Pseudoprime numbers 米勒拉宾素数判定+埃氏筛法

news2025/1/12 8:50:58

一、思路

对于输入的一个数字n和a,我们用快速幂判断 n ^ a % n 是否等于n,如果不等于直接输出no,等于的话,再判断n是否为素数,如果n为素数,输出no,否则输出yes。

判断素数的话,对于30000以下的,我采用埃氏筛法打表,对于3000以上的,我用米勒拉宾判断。

米勒拉宾算法,就是求出一组r和d,使得 d * 2 * r = n-1,产生小于n大于0的随机数m,判断m ^ (n - 1) == 1 (mod n)是否成立,成立的话,再定义i从0到r-1循环,判断每一个 (m ^ d)^(2^i)是否为1或者p-1,如果是的话,直接判断过,如果都不是,那么n不是素数。

二、代码

#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
ll r, d;
int primeLimit = 30000;
bool isPrime[30007];
void sieve()
{
    for (int i = 0; i <= primeLimit; i++)
    {
        isPrime[i] = true;
    }
    isPrime[0] = false;
    isPrime[1] = false;
    for (int i = 1; i * i <= primeLimit; i++)
    {
        if (!isPrime[i])
        {
            continue;
        }
        for (int j = 2 * i; j <= primeLimit; j += i)
        {
            isPrime[j] = false;
        }
    }
}
void getRd(ll p)
{
    d = p - 1;
    r = 0;
    while (!(d & 1))
    {
        d = d >> 1;
        r++;
    }
}
ll getLongRand(ll p)
{
    int x = 0;
    while (x == 0)
    {
        x = rand();
        if (x < 0)
        {
            x = x * (-1);
        }
        if (x >= p)
        {
            x = x % p;
        }
    }
    return (ll)x;
}
ll mulMod(ll a, ll b, ll mod)
{
    ll res = 0;
    while (b)
    {
        if (b & 1)
        {
            res = (res + a) % mod;
        }
        a = (a << 1) % mod;
        b = b >> 1;
    }
    return res;
}
ll powMod(ll a, ll b, ll mod)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = mulMod(res, a, mod);
        }
        a = mulMod(a, a, mod);
        b = b >> 1;
    }
    return res;
}
bool millerRabin(ll p)
{
    ll a = getLongRand(p);
    if (powMod(a, p - 1, p) != 1)
    {
        return false;
    }
    ll k = powMod(a, d, p);
    for (int i = 0; i < r; i++)
    {
        ll parameter = powMod(k, powMod(2, i, p), p);
        if (parameter == 1 || parameter == p - 1)
        {
            return true;
        }
    }
    return false;
}
bool multipleMillerRabin(ll p)
{
    getRd(p);
    for (int i = 0; i < 20; i++)
    {
        if (!millerRabin(p))
        {
            return false;
        }
    }
    return true;
}
bool judgePrime(ll p)
{
    if (p <= primeLimit)
    {
        return isPrime[(int)p];
    }
    else if (!(p & 1))
    {
        return false;
    }
    else
    {
        return multipleMillerRabin(p);
    }
}
bool fermet(ll a, ll p)
{
    return powMod(a, p, p) == (a % p);
}
int main()
{
    sieve();
    ll a, p;
    while (true)
    {
        scanf("%lld%lld", &p, &a);
        if (a == 0 && p == 0)
        {
            break;
        }
        if (fermet(a, p) && !judgePrime(p))
        {
            printf("yes\n");
        }
        else
        {
            printf("no\n");
        }
    }
    return 0;
}

三、我对米勒拉宾算法个人小小理解

// 这里引入费马小定理, 当 p 时一个素数时,对任意的整数a,一定有 pow ( a , p ) % p == a % p
// 当 1 <= a <= p - 1 我们对等式两边同时除以 a,得到 pow ( a , p - 1 ) % p == 1
// 所以只要对于大整数 p 和随机数 a ,如果不满足这个规则,那么p一定不是素数
// 为了提高算法的准确性,我们把 pow ( a , p - 1 ) % p == 1 进行推导,这里用  a ^ (p-1) 代表a的 p - 1 次方
//  a ^ ( p - 1 ) % p == 1
// 定义 r d,使得 ( 2 ^ r ) * d = p - 1
// a ^ ( ( 2 ^ r ) * d ) % p == 1
// ( a ^ ( ( 2 ^ r ) * d ) - 1 ) % p == 0
// 这里可以使用平方差公式进行推导
// (a ^ ( (2 ^ (r - 1) ) * d) - 1) * (a ^ ( (2 ^ (r - 1) ) * d) + 1 ) % p == 0
// (a ^ ( (2 ^ (r - 2) ) * d) - 1) * (a ^ ( (2 ^ (r - 2) ) * d) + 1 ) * (a ^ ( (2 ^ (r - 1) ) * d) + 1) % p == 0
// ....
// (a ^ ( (2 ^ (r - r) ) * d) - 1) * (a ^ ( (2 ^ (r - r) ) * d) + 1) * ...  (a ^ ( (2 ^ (r - 1) ) * d) + 1) % p == 0
// 同时p是素数,如果这些项相乘 % p == 0,那么其中的某一项一定等于0,那么就推出了另外一个判断依据
// 在  0 <= i < r 必定存在 a ^ ( (2 ^ i) * d) 等于 p 或等于 1,否则 p 一定不是素数
// a ^ ( (2 ^ i) * d) = (a ^ d) ^ (2 ^ i)




四、运行情况

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/897549.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

德赛西威半年报:竞争加剧,座舱乏力?智驾继续保持高增速

作为国内头部的智能网联核心软硬件供应商&#xff0c;德赛西威的表现&#xff0c;也在一定程度上反映了市场的行情走向&#xff0c;也凸显不同细分赛道的竞争白热化。 半年报数据显示&#xff0c;2023年1-6月&#xff0c;德赛西威实现营业收入87.24亿元&#xff0c;同比增长36.…

【LeetCode75】第三十三题 二叉树的最大深度

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 从这一题开始&#xff0c;LeetCode75进入到了二叉树章节。 这边建议不熟悉二叉树的小伙伴可以先去做做力扣的前序遍历&#xff0c;中序遍…

Azure存储访问层

blob数据的热访问层&#xff0c;冷访问层和存档访问层 Azure Blob 存储是一种托管对象存储服务&#xff0c;可用于存储和访问大量非结构化数据&#xff0c;如文本和二进制数据。Azure Blob 存储提供了三个不同层级的访问方式&#xff0c;以适应不同数据的使用模式和成本效益需…

基于GUI的卷积神经网络和长短期神经网络的语音识别系统,卷积神经网的原理,长短期神经网络的原理

目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 长短期神经网络的原理 基于GUI的卷积神经网络和长短期神经网络的语音识别系统 代码下载链接:基于MATLABGUI编程的卷积神经网络和长短期…

XQuery创建BaseX数据库实例

XQuery创建BaseX数据库实例 文章目录 XQuery创建BaseX数据库实例1、准备工作2、demo目录结构3、IDEA配置BaseX4、工具类BaseXClient5、Example 1、准备工作 开发工具&#xff1a; IDEAOxygen 技术&#xff1a; JavaBaseXXpathXquery BaseX需要阅读的文档&#xff1a; htt…

【学习日记】【FreeRTOS】延时列表的实现

前言 本文在前面文章的基础上实现了延时列表&#xff0c;取消了 TCB 中的延时参数。 本文是对野火 RTOS 教程的笔记&#xff0c;融入了笔者的理解&#xff0c;代码大部分来自野火。 一、如何更高效地查找延时到期的任务 1. 朴素方式 在本文之前&#xff0c;我们使用了一种朴…

二进制数的左移和右移位运算numpy.left_shift()numpy.right_shift()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 二进制数的左移和右移位运算 numpy.left_shift() numpy.right_shift() [太阳]选择题 下列代码最后一次输出的结果是&#xff1f; import numpy as np a 8 print("【显示】a ", a)…

AgentBench::AI智能体发展的潜在问题(二)

从历史上看&#xff0c;几乎每一种新技术的广泛应用都会在带来新机遇的同时引发很多新问题&#xff0c;AI智能体也不例外。从目前的发展看&#xff0c;AI智能体的发展可能带来的新问题可能包括如下方面&#xff1a; 第二是AI智能体的普及将有可能进一步加剧AI造成的技术性失业。…

无脑入门pytorch系列(四)—— scatter_

本系列教程适用于没有任何pytorch的同学&#xff08;简单的python语法还是要的&#xff09;&#xff0c;从代码的表层出发挖掘代码的深层含义&#xff0c;理解具体的意思和内涵。pytorch的很多函数看着非常简单&#xff0c;但是其中包含了很多内容&#xff0c;不了解其中的意思…

【云原生】k8s存储管理中ConfigMap Secret的使用

目录 1 ConfigMap 1.1 简介 1.2 优点 1.3 定义 ConfigMap 1.4 使用 2 Secret 2.1 简介 2.1 定义 Secret 2.2 使用 1 ConfigMap 1.1 简介 在 Kubernetes 中&#xff0c;ConfigMap 是一种用于存储非敏感信息的 Kubernetes 对象。它用于存储配置数据&#xff0c;如键值…

【Redis从头学-4】Redis中的String数据类型实战应用场景之验证码、浏览量、点赞量、Json格式存储

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;Re…

融媒行业落地客户旅程编排,详解数字化用户运营实战

移动互联网时代是流量红利的时代&#xff0c;企业常用低成本的方式进行获客&#xff0c;“增长黑客”的概念大范围传播。与此同时&#xff0c;机构媒体受到传播环境的影响&#xff0c;也开始启动全行业的媒体融合转型。在此背景下&#xff0c;2015 年神策数据成立&#xff0c;核…

数据结构,线性表与线性结构关系,顺序表与顺序结构关系,线性表与顺序表关系

学习数据结构会出现很多的概念如顺序结构&#xff0c;非线性结构&#xff0c;顺序表&#xff0c;顺序结构&#xff0c;顺序表&#xff0c;链表&#xff0c;栈&#xff0c;队列&#xff0c;堆等。今天来小讲以下其中的线性表与线性结构&#xff0c;顺序表与顺序结构的关系。 在数…

Nginx虚拟主机(server块)部署Vue项目

需求 配置虚拟主机&#xff0c;实现一个Nginx运行多个服务。 实现 使用Server块。不同的端口号&#xff0c;表示不同的服务&#xff1b;同时在配置中指定&#xff0c;Vue安装包所在的位置。 配置 Vue项目&#xff0c;放在 html/test 目录下。 config中的配置如下&#xf…

每日一题 141环形链表(快慢指针)

题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

FANUC机器人加减速倍率指令ACC的使用方法说明

FANUC机器人加减速倍率指令ACC的使用方法说明 单位有一台FANUC机器人(型号:M-900iB 360kg),偶尔会在启动的瞬间会报SRVO-050碰撞检测报警,而事实上机器人并没有开始移动或和其他工件产生碰撞,一直查了很长时间,也没有查到具体的原因,也尝试过重新进行负载推算,但是偶尔…

【C++11保姆级教程】移动构造函数(move constructor)和移动赋值操作符(move assignment operator)

文章目录 前言一、移动构造函数&#xff08;Move Constructor&#xff09;1.1 移动构造函数是什么&#xff1f;1.2 基本格式1.3 示例代码1.4 输出结果 二、移动赋值操作符&#xff08;Move Assignment Operator&#xff09;2.1 移动赋值操作符是什么&#xff1f;2.2 一般格式2.…

SpringBoot + Vue 微人事项目(第二天)

昨天做了微人事登录的前端页面和后端接口&#xff0c;实现了前后端接口的对接&#xff0c;输入正确的用户名和密码之后&#xff0c;成功的跳转到home页。现在要做的就是Home页的Title制作 Home页的title制作 使用Element UI中的Container布局容器 复制的代码如下&#xff0c…

redis十种数据类型及底层原理

概述 Redis 是一个开源的高性能键值数据库&#xff0c;它支持多种数据类型&#xff0c;可以满足不同的业务需求。本文将介绍 Redis 的10种数据类型&#xff0c;分别是 string&#xff08;字符串&#xff09; hash&#xff08;哈希&#xff09; list&#xff08;列表&#xf…

【C++】函数指针

2023年8月18日&#xff0c;周五上午 今天在B站看Qt教学视频的时候遇到了 目录 语法和typedef或using结合我的总结 语法 返回类型 (*指针变量名)(参数列表)以下是一些示例来说明如何声明不同类型的函数指针&#xff1a; 声明一个不接受任何参数且返回void的函数指针&#xf…