数论总结1

来源:互联网 发布:linux c 字符串拷贝 编辑:程序博客网 时间:2024/05/21 02:49

费马小定理: 假如p是质数,且(a,p)=1,那么 a^(p-1) ≡1(mod p) 假如p是质数,且a,p互质,那么 a的(p-1)次方除以p的余数恒等于1。该定理的逆否命题也成立,即a^(n-1)mod n!=1,则n为合数.但是费马定律的逆命题就不一定成立了,比如当a=4,n=15时,4^14mod15=1,但是4不是素数而是合数.

快速模取幂

    数论计算中经常出现的一种运算就是求一个数的幂ab对另外一个数n个模的运算,即计算:

ab mod n (a,b,n是正整数)

    由于计算机只能表示有限位的整数,所以编程时模取幂的运算要注意值的大小范围,当ab的值超过整数范围时,mod运算便无法进行。

    如何解决这个问题,我们引出一个能计算ab mod n的值的有用算法——反复平方法,首先我们必须明确:

d=ab mod n=(…((((a mod n)*a)mod n)*a)mod n…*a)mod n    {共b个a}

    由此可以引出一个迭代式

         d:=a;

         for i:=2 to b do

            d:=d mod n*a;

         d:=d mod n;

    时间复杂度为O(b),当b很大时,效率很低。我们可以将b转换为二进制数<bk,bk-1,...,b1,b0>,然后从最低位b0开始,由右至左逐位扫描,每次迭代时,用到下面两个恒等式:

a mod n =(ac)2 mod n      bi=0            

a+1 mod n =a*(ac)2 mod n   bi=1 (0<=c<=b)

    其中c为b的二进制数的后缀(bi-1...b0)对应的十进制数,当c成倍增加时,算法保持d=ac mod n不变,直至c=b。

     程序实现可如下:

long long result(long long a,long long b,long long m)
{
    long long d,t;

    d=1;
    t=a;
    while (b>0)
    {
        if (b%2==1)
            d=(d*t)%m;
        b/=2;
        t=(t*t)%m;
    }

    return d;
}

米勒-拉宾算法:快速判断一个数是不是素数

要测试 N 是否为质数,首先将 N-1分解为 2^s d。在每次测试开始时,先随机选一个 介于 【1, n-1】的整数 a,之后如果对所有的 r \in 【0, s-1】,若a^d \mod N 不等于1  且  a^((2^r)*d) mod N不等于 -1,则 N 是合数。否则,N 有 3/4 的机率为质数。

算法模板:

  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. int fmod(int a, int b, int c)//快速模取幂  
  6. {  
  7.     if(b == 1) return a;  
  8.     int t = fmod(a, b / 2, c);  
  9.     t = (t * t) % c;  
  10.     if(b & 1) t = (t * a) % c;  
  11.     return t;  
  12. }  
  13.   
  14. int check(int n)//米勒-拉宾算法  
  15. {  
  16.     srand(time(0));  
  17.     for(int i = 0; i < 100; ++ i)  
  18.     {  
  19.         if(fmod(rand() % (n - 1) + 1, n - 1, n) != 1)//a的值需要变化,所以用到随机函数;a的取值为[1,n-1],因为这样就会保证如果n为素数,则n与a必互质  
  20.             return 0;  
  21.     }  
  22.     return 1;  
  23. }  

原创粉丝点击