数论几个简单定理的总结

定理一:(除法定理)对于任何整数a和任何正整数n,存在唯一的整qr,满足0<=ra = qn + r

证明略

 

定理二gcd(x,y) = d,当ax + by为正整数时有 min(ax + by) = d;

显然当gcd(x,y) = 1 时。就是ax + by = 1

证明:                   

设集合Sxy的线性组合ax+by的集合,其中a,b为整数                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         

0 < x^2 + y^2可知S中有正整数,由最小自然数原理可知,S中存在最小正正数,设为s0,那么首先d|s0,所以d<=s0

第二,对于x,和的其中任意一个,如果除以s0余数是r1r2。那么可知r1,r2也属于S.所以r1 = r2 = 0.s0能整除xy所以s0x,y的最大公约数。

定理三:lcm(a,b) = ab/gcd(a,b) 证明略

定理四:假设gcd(n,m) = d,那么 b (mod n)且 ab( mod m)等价于 ab mod( lcm(n,m));

证明略

 

定理五:  b (mod nm) 推出   b (mod m) ,a  b(mod n) 

 

 

 

 

一、扩展欧几里得算法

扩展欧几里德算法是用来在已知a, b求解一组xy使得

ax+by = Gcd(a, b) = d两边除以d,得到a'x+b'y=1,a'b'是互质的,根据上面的定理,肯定是有正数解的)。扩展欧几里德常用在求解模线性方程及方程组中。

         

现在求解 ax+by=1

假设a>ba=kb+ll)则上式可以写成(k * b+lx+by = l * x+b * (k * x+y) = 1,y' = k * x+y,则方程为l * x + b * y' = 1

则此方程的解x为原方程的解,y = (y' - k*x)

则上述可以证明扩展欧几里得算法的正确性

给出代码:


void exgcd(int a, int b, int& d, int& x, int& y)  
{
   if(!b) { d = a; x = 1; y = 0; }  
   else  { exgcd(b, a % b, d, y, x); y -= x * (a / b); }  
}  


这样就可以求出一组解x,y

假设另外一组解为x1,y1

那么a(x-x1)=b(y-y1)

两边除以gcd(a,b)

则,a'(x-x1) = b'(y-y1),其中 a'=a/gcd(a.b)b'=b/gcd(a.b)

由于a',b'互素,x - x1 b'的倍数,设为kb‘得(y - y1=ka'可以 求出所有的xy

 

关于ax+by=c c不是gcd(a,b)时无解

由上面当c为为k*gcd(a,b)时,一组解为(kx,ky(x,y) ax+by=gcd(a,b)的一组解

c不是gcd(a,b)的倍数时,显然无解,因为左边是最小公约数的 倍数,右边不是

 

 

扩展:欧几里得算法可以求多于2元的模线性方程,显然不断迭代就可以解出来了。

 

扩展欧几里得算法通常解决如下三种问题

 

1)求解不定方程;

2)求解模线性方程(线性同余方程);

3)求解模的逆元;

另外两个问题可以转化成我们熟悉的方式(1)求解

 

 

求解逆元:

 

 模P乘法逆元

 对于整数ap,如果存在整数b,满足a*b mod p =1,则说,ba的模p乘法逆元。

 定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1

 证明:

 充分性:

 如果gcd(a,p) = 1,根据欧拉定理,a^φ(p) ≡ 1 mod p,因此

 显然aφ(p) - 1 mod pa的模p乘法逆元。

 必要性:

 假设存在 a mod p的乘法逆元为b

 ab ≡ 1 mod p

 则ab = kp +1 ,所以1 = ab - kp

 因为gcd(a,p) = d

 所以d | 1

 所以d只能为

 

 

可以由1 = ab - kp求出bk

计算ap的乘法逆元

下面代码算出a,b的最大公约数和b的逆元ar,以及ba的逆元br(用非递归的计算)

int gcd(int a,int b,int &ar,int &br){
    int x1,x2,x3;
    int y1,y2,y3;
    int t1,t2,t3;
    if(0 == a){//有一个数为0,就不存在乘法逆元
        ar = 0;br = 0 ;
        return b;
    }
    if(0 == b){
        ar = 0;
        br = 0 ;
        return a;
    }
    x1 = 1; x2 = 0; x3 = a; y1 = 0; y2 = 1; y3 = b; int k;
    for( t3 = x3 % y3 ; t3 != 0 ; t3 = x3 % y3){
        k = x3 / y3;
        t2 = x2 - k * y2;t1 = x1 - k * y1;
        x1 = y1;
        x2 = y2;
        x3 = y3;
        y1 = t1;
        y2 = t2;
        y3 = t3;
    }
    if( y3 == 1){//有乘法逆元
        ar = y2; br = x1;
        return 1;
    }
    else{//公约数不为1,无乘法逆元
        ar = 0;br = 0;return y3;
    }
}
 


递归计算:

bigint inv(bigint a, bigint n) {
    bigint d, x, y;
    Gcd(a, n, d, x, y);
    if (d == 1) return ( x % n + n) % n;
    else return -1;
}
 


二、中国剩余定理

有一个数x,除以n个模数a[0],a[1]……a[n-1](所有模数 两两互质)后,得到n个余数r[0],r[1]……r[n-1],求x

先看三个方程的情况

X mod 3 = 2

X mod 5 = 3

X mod 7 = 2

构造法求解:

我们可以求k1,k2,k3

使得: k1 mod 3 = 2, k2 mod 3 = k3 mod 3 = 0

                  k2 mod 5 = 3, k1 mod 5 = k1 mod 5 = 0

    K3 mod 7 = 2,k1 mod 7 = k2 mod 7 = 0

每个k都由独立的三个方程确定,就可以解出 k1,k2,k3了。

k1,k1 = k*35。我们可以先解出k

由 k * 35 mod 3 = 2可以得到不定方程

K*35 - 2 = 3*y,即:35k - 3y = 2,这个可以由扩展欧几里得算法求出。

K1,k2也可以按照同样的方法算出来。最后k1+k2+k3,就是一个答案。  

一般的求解过程:

1)令p = a[0]*a[1]*……*a[n-1]k[i]=p/a[i]

2) 我们要找到这样的数  d[i]%k[i]==0

    d[i]%a[i]==r[i]0n-1(这里可以用

    到扩展欧几里德算法来求得d[i])

3)当求出d[0],d[1],d[2]……d[n-1]后,相加得  

     到ww为其中一个解,且通解x = w + t*p  (t  

     为任意自然数)

中国剩余定理一个条件就是模数要两两互素(条件非常苛刻),怎么求解一般的线性模方程,也就是模数不满足两两互素的情况。数论里的一般解法是分解因子,但是编程难度比较大,时间复杂度也比较高,这里采用的解法是将所有方程合并成一个方程求解。

假设有 x mod m1 = a

 x mod m2 = b

 Gcd(m1,m2) = d

 m1 = m1’d

 m2 = m2’d

那么,x = k1m1 + a 

x = k2m2 + b 

k1m1 + a = k2m2 + b,得 k1m1’ - k2m2’ = (b - a)/d ② .所以有解的情况肯定有 d|(b - a)  (这是充要条件,是判断有没有解的依据)。② 式可以用扩展欧几里得算法求出k1的一个解,我们先设为k那么k1的通解就是k + tm2’.将其代入①,得到x = t*lcm(m1,m2) + km1 + a,即  km1 + a (mod  lcm(m1,m2))这样就完成了两个式子的合并。按照此方法将所有方程合并成一个求解即可。复杂度是O(nlog(max{mi})

练习:poj 2891 

 

 

三、埃拉托斯特尼筛法

// 1:这是最原始的筛法,还有待优化 

#define Max 1000000
bool prime[Max];
void IsPrime(){
int t=(int)sqrt(Max*1.0);
     prime[0]=prime[1]=0;prime[2]=1;
     for(int i=3;i


优化1

 

#include
using namespace std;    
const long N = 200000;   
long prime[N] = {0},num_prime = 0;    
int isNotPrime[N] = {1, 1};   
int main()    
{     
     	for(long i = 2 ; i < N ; i ++)       
       	{            
if(! isNotPrime[i])               
 	prime[num_prime ++]=i;  
//关键处1        
for(long j = 0 ; j < num_prime && i * prime[j] <  N ; j ++)
    	{               
      	isNotPrime[i * prime[j]] = 1;  
  	if( !(i % prime[j] ) )  //关键处2                  
break;           
}        
}        
return 0;   
}  


首先,先明确一个条件,任何合数都能表示成一系列素数的积。

 

不管 是否是素数,都会执行到“关键处1”,

 

①如果 都是是素数的话,那简单,一个大的素数 乘以不大于 的素数,这样筛除的数跟之前的是不会重复的。筛出的数都是 N=p1*p2的形式, p1p2之间不相等

 

②如果 是合数,此时 可以表示成递增素数相乘 i=p1*p2*...*pn, pi都是素数(2<=i<=n),  pi<=pj  ( i<=j )

p1是最小的系数。

根据“关键处2”的定义,当p1==prime[j] 的时候,筛除就终止了,也就是说,只能筛出不大于p1的质数*i

证明略

优化2

 易于理解。 只算奇数部分,时空效率都还不错!

half=SIZE/2; 
int sn = (int) sqrt(SIZE); 
for (i = 0; i < half; i++) 
   p[i] = true;// 初始化全部奇数为素数。p[0]对应3,即p[i]对应2*i+3 
for (i = 0; i < sn; i++) {    
if(p[i])//如果 i+i+3 是素数
{     
    for(k=i+i+3, j=k*i+k+i; j < half; j+=k) 
    // 筛法起点是 p[i]所对应素数的平方 k^2                                        
    // k^2在 p 中的位置是 k*i+k+i
    //    下标 i         k*i+k+i
    //对应数值 k=i+i+3   k^2         
       p[j]=false; 
} 
} 
//素数都存放在 p 数组中,p[i]=true代表 i+i+2 是素数。
//举例,3是素数,按3*3,3*5,3*7...的次序筛选,因为只保存奇数,所以不用删3*4,3*6....


原始的埃拉托斯特尼筛法的渐进时间复杂度是nlnlnn,可以当做O(n),通常情况下,它的效率已经足够。改进后的时间复杂度是均摊是O(n)

 

练习:hdu 1431 poj 2689

 

四、欧拉函数 和欧拉定理

数论,对正整数n欧拉函数是少于或等于n的数中与n互质的数的数目,它又称为Euler's totient functionφ函数

积性函数:如果gcd(n,m) = 1,f(nm) = f(n)f(m),则称函数f是积性的。

φ是积性的。

证明:如果(m,m’) = 1,那么当aa’分别取遍模m和模m’的完全剩余系时,a’m + am’取遍mm’的一个完全剩余系。又因为

(a’m + am’,mm’) = 1 <------> (a’m +am’,m) = 1,(a’m+am’,m’) = 1

<------>(am’,m) = 1,(a’m,m’) = 1 <-----> (a,m) = 1,(a’,m’) = 1

从而这φ个小于mm’且与mm’互素的数是这φ(m)φ(m')个数a’m + am’的最小正剩余,其中am互素,而a’与m’互素,从而有φ(mm’)=φ(m)φ(m’)

 

从而可以推出,其中p是素数,进而推出欧拉公式:

欧拉函数的性质:

(N%a==0 && (N/a)%a==0) 则有:φ(N)=φ(N/a)*a;

(N%a==0 && (N/a)%a!=0) 则有:φ(N)=φ(N/a)*(a-1);

 

n为奇数时有

 

 a^b a^(b%phi(c) + phi(c)) (mod c) b >= phi(c)) 

 

求单个欧拉函数值:

Int  euler(int x)
{
int i, res=x;
int m = (int)sqrt(x*1.0) + 1;
for (i = 2; i < m; i++)
if(x%i == 0) {
res = res / i * (i - 1);	//先进行除法是为了防止中间数据的溢出  
while (x % i == 0) x /= i; // 保证i一定是素数
}
if (x > 1) res = res / x * (x - 1);
return res;
}


递推求欧拉函数值:

 //筛选法打欧拉函数表   
 #define Max 1000001  
 int euler[Max];  
 void Init(){   
      euler[1]=1;  
      for(int i=2;i

欧拉定理:

na互质,那么

n为素数时,a^(n - 1)  1 mod n,这个称为费马小定理

引入一个定理:

定理:如果a1,a2,....aphi(m)是个与m互素的完全剩余系,且(k,m) = 1,那么(ka1,ka2,.....kaphi(m))仍然是一个与m互素的完全剩余系。

证明:  首先kaim显然互素,然后用反证法假设kai   kaj (mod m) 和(km) = 1,可以推出ai = aj 这即证明了定理

 

先证明费马小定理

证:

构造素数p

的既约剩余系

因为,由引理3可得

也是p的一个既约剩余系。由既约剩余系的性质,

         

易知   ,同余式两边可约去 

,得到  

这样就证明了费马小定理。

模仿上面证明,我们来证明欧拉定理,同样利用构造既约剩余系来证明。

证明欧拉定理

证:

我们构造模m的一个既约剩余系xi,那么

(ax)  mod m

a^phi(m) x   mod m

由于xm既约,直接消去,得a^phi(m)  1 ( mod m

其中am既约,即(a,m) = 1

.QED

你可能感兴趣的:(数论几个简单定理的总结)