#1287 : 数论一·Miller-Rabin质数测试--511186 质数检测 V2质数检测----【Miller-Rabin质数测试】

本文介绍了一种高效的质数测试方法——Miller-Rabin质数测试,并提供了C++及Java两种语言的实现代码。该方法适用于检测大数值是否为质数,通过随机选取的基数进行多次测试以提高准确率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#1287 : 数论一·Miller-Rabin质数测试

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

小Hi和小Ho最近突然对密码学产生了兴趣,其中有个叫RSA的公钥密码算法。RSA算法的计算过程中,需要找一些很大的质数。

小Ho:要如何来找出足够大的质数呢?

小Hi:我倒是有一个想法,我们可以先随机一个特别大的初始奇数,然后检查它是不是质数,如果不是就找比它大2的数,一直重复,直到找到一个质数为止。

小Ho:这样好像可行,那我就这么办吧。

过了一会儿,小Ho拿来了一张写满数字的纸条。

小Ho:我用程序随机生成了一些初始数字,但是要求解它们是不是质数太花时间了。

小Hi:你是怎么做的啊?

说着小Hi接过了小Ho的纸条。

小Ho:比如说我要检测数字n是不是质数吧,我就从2开始枚举,一直到sqrt(n),看能否被n整除。

小Hi:那就对了。你看纸条上很多数字都是在15、16位左右,就算开方之后,也有7、8位的数字。对于这样大一个数字的循环,显然会很花费时间。

小Ho:那有什么更快速的方法么?

小Hi:当然有了,有一种叫做Miller-Rabin质数测试的算法,可以很快的判定一个大数是否是质数。

提示:Miller-Rabin质数测试

输入

第1行:1个正整数t,表示数字的个数,10≤t≤50

第2..t+1行:每行1个正整数,第i+1行表示正整数a[i],2≤a[i]≤10^18

输出

第1..t行:每行1个字符串,若a[i]为质数,第i行输出"Yes",否则输出"No"

样例输入
3
3
7
9
样例输出
Yes
Yes
No

c++ 代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
LL cheng(LL a,LL b,LL mod)
{
    int ch[40]={0},ch2[40]={0};
    int lp1=0,lp2,ge;
    while (a)
    {
        ch[lp1++]=a%10;
        a/=10;
    }
    lp2=0;
    while (b)
    {
        ge=b%10;
        for (int i=lp2;i<lp2+lp1;i++)
        {
            ch2[i]=ch2[i]+ch[i-lp2]*ge;
            if (ch2[i]>9)
            {
                ch2[i+1]+=ch2[i]/10;
                ch2[i]%=10;
            }
        }
        b/=10;
        lp2++;
    }
    LL ans=0;
    for (int i=39;i>=0;i--)
    {
        ans=(ans*10+ch2[i])%mod;
    }
    return ans;
}
LL pp(LL a,LL n,LL mod)
{
    LL s=1,lp=a;
    while (n)
    {
        if (n%2)
        {
            s=cheng(s,lp,mod);
        }
        lp=cheng(lp,lp,mod);
        n/=2;
    }
    return s;
}
bool pan(LL a,LL n)
{
    if (n<2) return false;
    if (n==2) return true;
    if ((n&1)==0) return false;
    LL u=n-1;if (u<=a) return true;
    while (!(u&1)) u>>=1;
    LL t=pp(a,u,n);
    while ((u!=n-1)&&(t!=1)&&(t!=n-1))
    {
        t=cheng(t,t,n);
        u<<=1;
    }
    return (t==n-1||(u&1)==1);
}
int main()
{
    int t;scanf("%d",&t);
    LL a;LL shu[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
    while (t--)
    {
        bool fafe=true;
        scanf("%lld",&a);
        for (int i=0;i<12;i++)
        {
            fafe=pan(shu[i],a);
            if (!fafe) break;
        }
        printf("%s\n",fafe?"Yes":"No");
    }
    return 0;
}


基准时间限制:1 秒 空间限制:131072 KB 分值: 40  难度:4级算法题
 收藏
 关注
给出1个正整数N,检测N是否为质数。如果是,输出"Yes",否则输出"No"。
Input
输入一个数N(2 <= N <= 10^30)
Output
如果N为质数,输出"Yes",否则输出"No"。
Input示例
17
Output示例
Yes


java版:


import java.util.*;
import java.math.*;
public class Main{
	public static BigInteger  pp(int a,BigInteger n,BigInteger mo)
	{
		BigInteger s,lp,tw;
		tw=BigInteger.valueOf(2);
		s=BigInteger.ONE;
		lp=BigInteger.valueOf(a);
	    while (n.compareTo(BigInteger.ZERO)!=0)
	    {
	        if ((n.remainder(tw)).compareTo(BigInteger.ONE)==0)
	        {
	        	s=s.multiply(lp);
	        	s=s.remainder(mo);
	        }
	        lp=lp.multiply(lp);
	        lp=lp.remainder(mo);
	        n=n.divide(tw);
	    }
	    return s;
	}
	
	public static int pan(int a,BigInteger n)
	{
		
		if (n.compareTo(BigInteger.ONE.add(BigInteger.ONE))==0) return 1;
		BigInteger tw = BigInteger.ONE.add(BigInteger.ONE);
	    if (n.remainder(tw).compareTo(BigInteger.ZERO)==0) return 0;
	    BigInteger u;
	    u=n.subtract(BigInteger.ONE);
	    BigInteger aa=BigInteger.valueOf(a);
	    if (!(u.compareTo(aa)==1)) return 1;
	    while ((u.remainder(tw).compareTo(BigInteger.ZERO))==0) 
	    	u=u.divide(tw);
	    BigInteger t=pp(a,u,n);
	    while ((u.compareTo(n.subtract(BigInteger.ONE))!=0)&&(t.compareTo(BigInteger.ONE)!=0)&&(t.compareTo(n.subtract(BigInteger.ONE))!=0))
	    {
	        t=(t.multiply(t)).remainder(n);
	        u=u.multiply(tw);
	    }
	    
	    if  ( (t.compareTo(n.subtract(BigInteger.ONE))==0)||(  (u.remainder(tw)).compareTo(BigInteger.ONE)==0  )) return 1;
	    return 0;
	}
	
	
	public static void main(String args[]){
		Scanner cin = new Scanner(System.in);
		BigInteger n;
		int fafe;
		int shu[] = new int[25];
		shu[0]=2;shu[1]=3;shu[2]=5;shu[3]=7;shu[4]=11;shu[5]=13;shu[6]=17;shu[7]=19;shu[8]=23;shu[9]=29;shu[10]=31;shu[11]=37;shu[12]=41;
		shu[13]=43;shu[14]=47;shu[15]=53;shu[16]=59;shu[17]=61;shu[18]=67;shu[19]=71;shu[20]=73;shu[21]=79;shu[22]=83;shu[23]=89;shu[24]=97;
			n=cin.nextBigInteger();
			fafe=1;
			for (int i=0;i<25;i++)
			{
				fafe=pan(shu[i],n);
				if(fafe==0)
					break;
			}
			
			if (fafe==1)
				System.out.println("Yes");
			else
				System.out.println("No");
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值