Miller_Rabin随机素数测试+pollard_rho大数质因子分解(附例题Prime Test POJ - 1811)_x^p mod p=1 p为奇素数_Vici__的博客-程序员秘密

技术标签: private  

一、合数的Miller_Rabin测试:

理论基础:

  1. 费马小定理:设p是素数,a是任意整数且a与p互质,则a^(p-1)≡1(mod p).
  2. 二次探测定理:设p是素数,x是小于p的正整数,且x^2≡1(modp) , 则x = 1 或 x = p - 1;
    (易证:x^2≡1(mod p)   →  x^2-1≡(mod p)  →  (x+1)(x-1)≡ 0 (mod p)  →  (x+1)=p,(x-1)= 0  →  x = 1 或 x = p - 1)
  3. 【中心思想】拉宾-米勒素数测试:设n是奇数,记n-1=2^{k}*q,q是奇素数,对不被n整除的某个a,如果下述两个条件有一个成立,则n是素数
    a^{q}\equiv 1(modn)
    ②对于i=0,1,2……k-1,至少有一个i符合a^{2^{i}*q}\equiv -1(mod n)

    (如果n是个合数,则1~n-1之间至少有75%的数可作为n的拉宾-米勒证据,则经过10次测试可将成功率提高至0.999999046)

  4. 快速积取模、快速幂取模。

算法过程:

  1. n<2时不是素数,n==2是素数,n是偶数时不是素数;(特判)
  2. 将n-1分解为 n-1=2^{k}*q
  3. 用rand()函数随机取一个正整数a,且1<a<n;
  4. 根据上文理论基础3.②从i=0开始检测,共循环k次,若有符合的i,返回false,则证明是合数,循环结束后无i符合,返回true,证明是素数;
  5. 反复进行8~10次,可将正确率接近于100%;
  6. 多次测试均符合,则可确定n是个素数。
     

 二、pollard_rho大数质因子分解:

 算法过程(转):

给定:整数n(已知是合数);

目标:找到一个因子 d | n;

步骤:

  1. 固定整数B
  2. 选择一个整数k,k是大部分(或者全部)b的乘积满足b≤B;
  3. 选择一个随机整数a满足2 ≤ a ≤ n-2
  4. 计算 r=a^{k}(modn)
  5. 计算d=gcd(r-1,n)
  6. 如果d = 1 或者 d = n,返回步骤 2 ,否则,d就是要找的因子。

 附例题POJ1811(Prime Test )代码及代码详解:

#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <time.h>
using namespace std;
const int S = 10; //随机算法判定次数
// 计算 ret = (a*b)%c a,b,c < 2^63
long long mult_mod(long long a,long long b,long long c)
{
    a %= c;
    b %= c;
    long long ret = 0;
    long long tmp = a;
    while(b)
    {
        if(b & 1)
        {
            ret += tmp;
            if(ret > c)
                ret-= c;//直接取模慢很多
        }
        tmp <<= 1;
        if(tmp > c)
            tmp-= c;
        b >>= 1;
    }
    return ret;
}
// 计算 ret = (a^n)%mod(快速幂)
long long pow_mod(long long a,long long n,long long mod)
{
    long long ret = 1;
    long long temp = a%mod;
    while(n)
    {
        if(n & 1)
            ret = mult_mod(ret,temp,mod);
        temp = mult_mod(temp,temp,mod);
        n >>= 1;
    }
    return ret;
}
//通过a^(n-1)同余1(mod n)来判断是不是素数
// n-1=x*2^t 中间使用二次判断
//是合数返回true,不一定是合数返回false;
bool check(long long a, long long n ,long long x,long long t)
//a为一随机数,n为待检测数也是模,x为(n-1)除去2的倍数后的值,t为n-1所能分解出的2
{
    // n-1=x*2^t;
    long long ret = pow_mod(a,x,n);
    long long last = ret;
    for(int i = 1; i <= t; i++)
    {
        ret = mult_mod(ret,ret,n);
            if(ret== 1&&last!=1&&last!=n-1)
            return true;//合数
        last = ret;
    }
    if(ret != 1)
        return true;
    else
        return false;
}
//**************************************************
// Miller_Rabin 算法
// 是素数返回 true,(可能是伪素数),不是素数返回 false;
//**************************************************
bool Miller_Rabin(long long n)
{
    if( n < 2)
        return false;
    if( n == 2)
        return true;
    if( (n&1) == 0)
        return false;//偶数
    long long x = n - 1;
    long long t = 0;
    while( (x&1)==0 )
    {
        x >>= 1;
        t++;//x能分解出t个2。
    }
    srand(time(NULL));//随机数发生器的初始化函数
    for(int i = 0; i < S; i++)//进行S次检测,减少误差.
    {
        long long a = rand()%(n-1) + 1;//取 1<= a <N的随机数
        if( check(a,n,x,t) )
            return false;
    }
    return true;
}

//**********************************************
// pollard_rho 算法进行质因素分解
//**********************************************
long long factor[100];//质因素分解结果(刚返回时时无序的)
int tol;//质因数的个数 (0~n-1)

long long gcd(long long a,long long b)//欧几里得求最大公约数
{
    long long t;
    while(b)
    {
        t = a;
        a = b;
        b = t%b;
    }
    if(a >= 0)
        return a;
    else
        return -a;
}

//找出一个因子
long long pollard_rho(long long x,long long c)
{
    long long i = 1, k = 2;
    srand(time(NULL));
    long long a = rand()%(x-1) + 1;
    long long y = a;
    while(1)
    {
        i ++;
        a = (mult_mod(a,a,x) + c)%x;
        long long d = gcd(y - a,x);
        if( d != 1 && d != x)
            return d;
        if(y == a)
            return x;
        if(i == k)
        {
            y = a;
            k += k;
        }
    }
}
//对 n 进行素因子分解,存入 factor. k 设置为 107 左右即可
void findfac(long long n,int k)
{
    if(n == 1)
        return;
    if(Miller_Rabin(n))
    {
        factor[tol++] = n;
        return;
    }
    long long p = n;
    int c = k;
    while( p >= n)
        p = pollard_rho(p,c--);//值变化,防止死循环 k
    findfac(p,k);
    findfac(n/p,k);
}
int main()
{
    int T;
    long long n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d",&n);
        if(Miller_Rabin(n))
            printf("Prime\n");
        else
        {
            tol = 0;
            findfac(n,107);
            long long ans = factor[0];
            for(int i = 1; i < tol; i++)
                ans = min(ans,factor[i]);
            printf("%I64d\n",ans);
        }
    }
    return 0;
}

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Vici__/article/details/82942510

智能推荐

Android基础_子控件和父控件之间的焦点_adb state_focused父布局获取焦点_响码的博客-程序员秘密

这一此主要记录一下几个很有用的xml布局属性:android:descendantFocusability:该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。(例:AdapterView中的item中)属性的值有三种: beforeDescendants:子控件不需要焦点时父控件获取 afterDescendants:优先父级获取blocksDes

$ 用python处理Excel文档(1)——用xlrd模块读取xls/xlsx文档_weixin_30932215的博客-程序员秘密

本文主要介绍xlrd模块读取Excel文档的基本用法,并以一个GDP数据的文档为例来进行操作。1. 准备工作:1. 安装xlrd:pip install xlrd2. 准备数据集:从网上找到的1952~2012年中国国内GDP的数据,数据结构如下:2. 目标:将这份数据转换成json格式的数据3. 上代码#!/usr/bin/python# coding:utf-8# 用xlrd...

确认过眼神,这就是亚信科技的核心能力_中国云报的博客-程序员秘密

6月28日,上海,一年一度的MWC(世界移动大会),赴亚信科技之约!这已经是亚信科技连续第二年参加在上海举行的MWC。在移动通信领域,未来的趋势从未像今天这样清晰:5G、...

maven无法加载依赖jar包_一只想要飞上天的小菜鸟的博客-程序员秘密

问题:         pom.xml文件添加依赖支持无法加载依赖jar包,命令行运行 mvn install出现以下错误         解决方案:        修改eclipse中maven的用户设置

常见管理菜单(1)_item-head-td1_sYwb的博客-程序员秘密

管理菜单var headHeight = 25;var bodyHeight = 150;var objcount = 8;var step = 25;var moving = false;function showme(obj1, obj2){    if (moving)        return;    moving = true;    for(i=0;i        if (docu

学习 JAVA,有什么书籍推荐?学习的方法和过程是怎样的?_Java技术江湖的博客-程序员秘密

学了两年Java,对Java学习有一定心得,现在进了阿里,正好专心做Java,今天推荐给大家一些比较好的Java后端书籍。书是读不完的,但是知识可以是自己的,选择适合你自己的书单,可能是最佳的解决方案。再次强调下,有些书籍是因为当时有项目需要用到这方面技术才需要看的,比如云计算和大数据相关的书籍,单纯的Java学习者可以忽略这方面的书籍,特此提醒。晒一下我的书架吧,基本上把我两年多时间...

随便推点

金蝶云 操作插件(列表界面、维护界面)弹出提示信息_金蝶erpcloud可以在弹框中挂插件吗_凌晨四点♛的博客-程序员秘密

金蝶云 操作插件(列表界面、维护界面)弹出提示信息1.维护界面 弹出提示【注意】注册操作插件import clrclr.AddReference("System")clr.AddReference("System.Data")clr.AddReference("System.XML")clr.AddReference("System.Web.Extensions")clr.AddReference("Kingdee.BOS")clr.AddReference("Kingdee.BOS.

no module named cv2问题_Rani_zZ的博客-程序员秘密

【问题描述】python3.6文件中import cv2运行错误no module named cv2win10,64位,python 3.6,Anaconda3(64-bit),想装opencv3.4.0(最新版本)【解决方法一】Anaconda prompt里面直接输入pip install opencv-python【解决方法二】1.首先先下载一个opencv的...

c#常用类库----计算机信息类_GoodShot的博客-程序员秘密

using System;using System.Management;using System.Net;using System.Net.Sockets;using System.Text;using System.Diagnostics;using System.Text.RegularExpressions;namespace BaseFunction{ ///

React 源码剖析系列 - 生命周期的管理艺术_react怎么管理自己的生命周期?_风翻火焰的博客-程序员秘密

前言React 的主要思想是通过构建可复用组件来构建用户界面。所谓组件其实就是有限状态机,通过状态渲染对应的界面,且每个组件都有自己的生命周期,它规定了组件的状态和方法需要在哪个阶段进行改变和执行。有限状态机(FSM),表示有限个状态以及在这些状态之间的转移和动作等行为的模型。一般通过状态、事件、转换和动作来描述有限状态机,下面是描述组合锁状态机的模型图,包括5个状态、5个状态自转换、6个状态间转换和1个复位 RESET 转换到状态 S1。状态机,能够记住目前所处的状态,根据当前的状态可以做出相应.

springboot 实现微信小程序订阅消息的信息推送_唱跑雨淋淋的博客-程序员秘密

微信小程序订阅消息推送:参考官方文档关于小程序订阅消息「订阅消息」需要用户主动订阅消息通知,开发者才可向用户推送,也就是需要做本文第二大点,第1小点的操作,且用户同意之后才可1、一次性订阅消息:用户订阅一次后,开发者可下发一条消息,不限时间。若用户勾选了“总是保持以上选择,不再询问”且点击了允许,那么以后都默认同意订阅这条消息。用户不再做多次选择,开发者也避免了更繁琐的提醒。2、长期性订阅消息:用户订阅一次后,可长期下发多条消息。目前长期性订阅消息向政务、医疗、交通、金融、教育等线下公共.

如何在vue项目中引入防抖节流插件_import { debounce } from 'throttle-debounce_技术林的博客-程序员秘密

安装npm install throttle-debounce --save引入(哪里需要引哪里)节流import { throttle } from ‘throttle-debounce’; const throttleFunc = throttle(1000, false, (num) =&gt; { console.log('num:', num);}); // 也可以这样使用,因为默认情况下,是falseconst throttleFunc = throttle(

推荐文章

热门文章

相关标签