数论(Primer)

Posted W2W

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论(Primer)相关的知识,希望对你有一定的参考价值。

几个重要需要记住的内容:

1.欧几里得定理(辗转相除法)

int gcd(int a, int b){
    return b==0?a:gcd(b, a%b);
}

2.扩展欧几里得(求ax+by = gcd(a,b)的特解)

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

3.中国剩余定理

同余方程组

≡ a1(mod m1)

≡ a2(mod m2)

... ...

≡ ak(mod mk)

方程组所有的解的集合就是:

x1 = N1*a1 + N2*a2 + ... + Nk*ak
 
其中 Ni mod mi = 1,Ni = ai * ti , 可用欧几里得扩展定理求 ti. 其中M = m1*m2*m3····*mn;
 
 
 
 
 
 
    #include <iostream>  
    using namespace std;  
    //参数可为负数的扩展欧几里德定理  
    void exOJLD(int a, int b, int &x, int &y){  
        //根据欧几里德定理  
        if(b == 0){//任意数与0的最大公约数为其本身。  
            x = 1;  
            y = 0;  
        }else{  
            int x1, y1;  
            exOJLD(b, a%b, x1, y1);  
            if(a*b < 0){//异号取反  
                x = - y1;  
                y = a/b*y1 - x1;  
            }else{//同号  
                x = y1;  
                y = x1 - a/b* y1;  
            }  
        }  
    }  
    //剩余定理  
    int calSYDL(int a[], int m[], int k){  
        int N[k];//这个可以删除  
        int mm = 1;//最小公倍数  
        int result = 0;  
        for(int i = 0; i < k; i++){  
            mm *= m[i];  
        }  
        for(int j = 0; j < k; j++){  
            int L, J;  
            exOJLD(mm/m[j], -m[j], L, J);  
            N[j] = m[j] * J + 1;//1  
            N[j] = mm/m[j] * L;//2 【注】1和2这两个值应该是相等的。  
            result += N[j]*a[j];  
        }  
        return (result % mm + mm) % mm;//落在(0, mm)之间,这么写是为了防止result初始为负数,本例中不可能为负可以直接 写成:return result%mm;即可。  
    }  
      
      
    int main(){  
        int a[3] = {2, 3, 2};  
        int m[3] = {3, 5, 7};      
        cout<<"结果:"<<calSYDL(a, m, 3)<<endl;  
    }  

 

4.欧拉函数(求一个数前面的所有与这个数互质的数的个数)
 
 
 
 
 
 
 
  Euler函数表达通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数。euler(1)=1(唯一和1互质的数就是1本身)。
 
 
    //直接求解欧拉函数  
    int euler(int n){ //返回euler(n)   
         int res=n,a=n;  
         for(int i=2;i*i<=a;i++){  
             if(a%i==0){  
                 res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出   
                 while(a%i==0) a/=i;  
             }  
         }  
         if(a>1) res=res/a*(a-1);  
         return res;  
    }  
      
    //筛选法打欧拉函数表   
    #define Max 1000001  
    int euler[Max];  
    void Init(){   
         euler[1]=1;  
         for(int i=2;i<Max;i++)  
           euler[i]=i;  
         for(int i=2;i<Max;i++)  
            if(euler[i]==i)  
               for(int j=i;j<Max;j+=i)  
                  euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出   
    }  

 

 

 

以上是关于数论(Primer)的主要内容,如果未能解决你的问题,请参考以下文章

数论 逆元求解(扩展欧几里得算法+费马小定理)

数论--欧几里得定理(求最大公约数)

数论初步——欧几里得算法和唯一分解定理

数论之欧几里德算法

基础数论的一些名词和定理 [未完]

数论-算术基本定理