利用费马小定理进行素性测试

本文介绍如何利用费马小定理结合高精度算法、高精度求余和快速幂,来高效地测试一个数是否为素数。通过解决一道算法题,讨论了在大整数运算中可能出现的溢出问题以及解决方案。

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

利用费马小定理进行素性测试

Description

给出一个整数N,请利用费马小定理(Fermat’s Little Theorem)测试该数是否素数。
Input

多测试用例。每个测试用一行:一个正整数N ( 3 ≤ N ≤ 9223372036854775807 ,N的范围就是 long long 的范围。注意:本OJ不支持__int64这种类型,所以,如果要用 __int64类型,可直接把它改为 long long类型。__int64的输入输出用 %I64d ,long long的输入输出用%lld )
Output

每个测试用例输出一行结果:如果N是素数,输出yes,否则,输出no 。
Sample Input

127
5
67
68
Sample Output

yes
yes
yes
no

一开始的思路,只用了费马小定理的代码,递归次数太多了,如果数太大需要耗费很长时间才能计算出结果。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>


//费马小定理
long long fermat(long long a,long long n,long long m)
{
    //递归出口
    if(m==0)return 1;
    else if(m==1)
        return a;
    //递归
    else{
        if(m%2==0)
            return (fermat(a,n,m/2)%n*fermat(a,n,m/2)%n)%n;
        else
            return ((fermat(a,n,m/2)%n*fermat(a,n,m/2)%n)%n*a)%n;
    }
}


int main(void)
{
    long long n,a=0;
    scanf("%lld",&n);
    while(n>=3&&n<=9223372036854775807)
    {
        srand((unsigned)time(NULL));

        //生成一个足够大的随机数(64位)
        for(int i=0;i<4;i++)
        {
            a=a+rand();
            a=a<<16;
        }
        //求n的模
        a=a%n;
        if(a<2)a=2;


        if(fermat(a,n,n-1)==1)
            printf("yes\n");
        else
            printf("no\n");
        scanf("%lld",&n);

    }
    return 0;
}

对于这道题,如果单纯只用费马小定理的话来做这道算法的话呢,理论是可以的,但是时间复杂度太高,计算一个大的数时需要很长时间,所以出现了Time Limit Exceeded。所以不得不再去研究如何去设计一种可以快速得出结果的算法。(研究了好几天还是没有头绪,最后还是去请教了一位已经AC过这道题的师兄-.-)

师兄给出了做这道题的思路,对于这道题他使用一种高效又准确的算法,通过整合费马小定理+高精度算法+高精度求余+快速幂这几个算法来实现。首先我们先来了解一下什么是费马小定理、高精度算法、高精度求余和快速幂,这几个算法也挺容易理解的。

  • 费马小定理

费马小定理(Fermat’s little theorem)是数论中的一个重要定理,在1636年提出,其内容为: 假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p),即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。

注意:可以用费马小定理判断素数,但有一定概率是错误的。费马小定理只是素数的必要条件,不是充分条件,即:满足费马小定理的数不一定是素数。
虽然有一定的概率出错,但效率高,而且也可以通过使用随机数生成a 或者增加验证费马小定理的次数来减小出错率。

  • 高精度乘法

计算机内部直接使用int和double等数据类型储存数字是有范围限制的,如:C语言的int类型与开发环境平台有关,可能是16位(2^16),也可能是32位(2^32)。当数据运算大小超过范围后,计算机

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值