码迷,mamicode.com
首页 > 编程语言 > 详细

【数论算法基础理论与实现】

时间:2016-08-13 01:17:27      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:

 
【题目太正式了我还怎么写ヾ|≧_≦|〃】
【很简要】
【参考文献:《算法导论》、白书、天宇哥哥课件】

 

  

  1.基础

【除法定理】:对于任何整数a和正整数n,存在唯一整数q和r,满足0<=r<n且a=qn+r

  WARN:C++中貌似不完全遵守这个东西,n认为是|n|,并且a为负时r可以为负

【】 

 

  2.最大公约数

几条性质:gcd(a,b)=gcd(|a|,|b|)

     gcd(a,0)=|a|

     gcd(a,ka)=|a|  

     gcd(a,b)=gcd(b,a mod b) --->Euclid算法

     gcd(na,nb)=n*gcd(a,b) ---->Stein算法

     当k与b互为质数,gcd(ka,b)=gcd(a,b)---->Stein算法

     gcd(a,b)是a与b的线性组合集{ax+by: x,y belong z}中最小的元素

【Euclid算法、扩展欧几里德算法】

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

int lcm(int a,int b){
    return a/gcd(a,b)*b;
}

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-=(a/b)*x;}
}

ax+by=gcd(a,b)  --> (x0,y0)          //|x0|+|y0|最小,可能为负

-->   (x0+kb‘,y0-ka‘)   a‘=a/gcd(a,b)  //任意解(列等式推理)

ax+by=c --> if c%gcd(a,b)==0 -->(x0*c/g+kb‘,y0*c/g-ka‘)  else no int solvement  //直线上的整点
WARN: ax+by+c=0 c --> -c

 

【Stein算法】(改进后--更相减损术)

原文:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
改进:利用上面那个性质

 

 

 

 

优势:不用除法   高精/位运算都很方便搞

int stein(int a,int b){
    if(a==0||b==0) return a==0?b:a;
    if(a&1==0&&b&1==0) return 2*stein(a>>1,b>>1);
    if(a&1==0) return stein(a>>1,b);
    if(b&1==0) return stein(a,b>>1);
    return stein(min(a,b),abs(a-b));
}

 

 

 

 

  3.唯一分解定理(不说了)

 

  4.素数1

【一个整数a>1只能被平凡约数1和自身所整除】

【判素数】:

  (1)朴素

bool isP(int n){
    if(n<=1) return false;
    int m=sqrt(n)+1;
    for(int i=2;i<=m;i++)
        if(n%i==0) return false;
    return true;
}

 

  (2)Miller-Rabin(见下面)

【筛素数】:

  (1)【Eratosthenes筛法】 复杂度O(nlogn)

  [每一个质数筛掉它的倍数  一定有一个小于根号n的质因子]

const int N=1e9;
bool vis[N];

void era(int n){
    int m=sqrt(n)+1;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<=m;i++) if(!vis[i])
        for(int j=i*i;j<=n;j+=i) vis[j]=true;
}

 

  (2)【欧拉筛法】 复杂度O(n)

  [对于任意一个合数,我们可以拆成最小质数*某个数字的形式。

  我们枚举『某个数字』i(区分与埃氏筛法的枚举质因数),然后再从第一个质数开始枚举,进行筛选。

  为了保证每个合数只被最小质因数筛选,当我们枚举的质数可以整除『某个数字』时,如果再往大里枚举,枚举的质数就不可能是最小质数了]

bool flag[N];
int prime[N];

int euler(int n){
    int cntprime=0;
    for(int i=2;i<=n;i++){
        if(!flag[i]) prime[++cntprime]=i;
        for(int j=1;j<=cntprime&&prime[j]*i<=n;j++){
            flag[prime[j]*i]=true;
            if(i%prime[j]==0) break;
        }
    }
    return cntprime;
}

 

   5.同余、模

【符号太难打 不说了】

【+ - *  在%n时的性质太常用 不说了】

剩余系Zn:对于一个正整数n,一个整数集模n所得的余数域。[0,n-1]

[a]n={a+kn : k belong z} 包含a的模n等价类

Zn={[a]n : 0<=a<=n-1}={0,1,2,...,n-1}

----------

逆元:ax===1(mod n)    x:a关于模n的逆元(inverse) ---------gcd(a,n)=1时唯一解,否则无解

同余系除法:乘以逆元

【解模线性方程】

  ax===b(mod n) ------> ax-ny=b --->d=gcd(a,n)是b的约数则有解 

  ------->直接用exgcd,然后x=x+k*(n/gcd(a,n))变正

  ------->(白书训练指南p126还有点东西 如恰好gcd(a,n)个解))

【求逆元】

  同上

//ax===1(mod n)  Zn:ax=1
//ax-ny=1 --> gcd(a,n)=1
//x -->all y that x===y(mod n)
int inv(int a,int n){
    int d,x,y;
    exgcd(a,n,d,x,y);
    return d==1?(x+n)%n:-1; //we need x and x is probably -
}

 

 

 

 

  6.素数2

【互质数】:两个整数a,b满足gcd(a,b)=1

【约数的个数】:对于n=p1^a1*p2^a2*...*pk^ak, 约数的个数=PI(ai+1):i=1..k=(a1+1)(a2+1)...(ak+1)  <--乘法原理

【欧拉函数】:对于n=p1^a1*p2^a2*...*pk^ak,phi(n)=n(1-i/p1)(1-1/p2)...(1-i/pk)   phi(1)=1   <--容斥原理+公式变形

  -------------Zn* 缩系:小于n且与n互质  |Zn*|=phi(n)

【计算欧拉函数】:

  (1) 单个 根号n求唯一分解算公式就行了

  (2) 一片 类似素数筛发,找到一个素数把它的倍数(包括自己)乘上(i-1)/i

int phi(int n){
    int m=sqrt(n+0.5);
    int ans=n;
    for(int i=2;i<=m;i++) if(n%i==0){
        ans=ans/i*(i-1);
        while(n%i==0) n/=i;
    }
    if(n>1) ans=ans/n*(n-1);    //n self is prime
    return ans;
}

const int N=1e6;
int a[N];
void initPhi(int n,int *phi){
    for(int i=2;i<=n;i++) phi[i]=0;
    phi[1]=1;
    for(int i=2;i<=n;i++) if(!phi[i])
        for(int j=i;j<=n;j+=i){
            if(!phi[j]) phi[j]=j;
            phi[j]=phi[j]/i*(i-1);
        }
}

 

【素数定理】:pi(n) = n/ln n  (略大)

【欧拉定理】: a^phi(n) === 1(mod n)

    Zn+ 非零 --->if n is prime ->Zn+=Zn*

【费马定理】: 假如p is prime,且a p互质,则 a^(p-1) ===1(mod n)

--------------【求逆元】时 当n is prime,直接a^(n-2) %n

【Miller-Rabin】质数检测(太喜欢这个了 见下一篇文章)

 

 

 

 

 

 

 

 

【数论算法基础理论与实现】

标签:

原文地址:http://www.cnblogs.com/candy99/p/5765986.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!