数论基础总?结?

Posted wo-shi-zhen-de-cai

tags:

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

  • \\(gcd\\)

    inline int gcd(int a,int b) return b?gcd(b,a%b):a;
  • 扩展欧几里得:求\\(ax+by=gcd(a,b)\\)的一组整数解。

    inline int Exgcd(int a,int b,int &x,int &y)
    
      if(!b) x=1,y=0;return a;
      int Gcd=Exgcd(b,a%b,y,x);
      y-=a/b*x;return Gcd;
    
  • 费马小定理:\\(a^p-1\\equiv 1\\mod p\\)\\(p\\)为质数)

  • 欧拉定理(\\(gcd(a,n)\\ne 1\\)):(無駄?)
    \\[ a^b\\equiv \\left\\\\beginarrayll a^b & b<\\varphi(n)\\\\a^b\\mod\\varphi(n)+\\varphi(n) & b\\geq \\varphi(n)\\endarray\\right.\\mod n \\]

  • 欧拉定理(\\(gcd(a,n)=1\\)):\\(a^\\varphi(n)\\equiv 1\\mod n\\)(無駄?)

  • 中国剩余定理(孙子定理):\\(p_1,p_2,p_3...p_k\\)两两互质,求一下方程组的最小整数解
    \\[ \\left\\\\beginarrayllx\\equiv a_1\\mod p_1\\\\x\\equiv a_2\\mod p_2\\\\...\\\\x\\equiv a_k\\mod p_k\\endarray\\right. \\]
    \\(P=\\prod p_i\\)\\(P_i=\\fracPp_i\\)\\(t_i,P_i\\)满足\\(t_iP_i\\equiv1\\mod p_i\\)

    所以最小整数解为:\\(x=\\sum a_iP_it_i \\mod P\\)

    inline int Exgcd(int a,int b,int &x,int &y)
    
      if(!b) x=1,y=0;return a;
      int Gcd=Exgcd(b,a%b,y,x);
      y-=a/b*x;return Gcd;
    
    int main()
      n=read();
      for(int i=1;i<=n;i++) p[i]=read(),a[i]=read(),P*=p[i];
      for(int i=1;i<=n;i++)
      
          int Pi=P/p[i],x,y;Exgcd(Pi,p[i],x,y);
          ans=(ans+a[i]*Pi*((x%p[i]+p[i])%p[i]))%P;
      
      printf("%lld",ans);
    
  • 扩展中国剩余定理(儿子定理\\(p_1,p_2,p_3...p_k\\)不一定两两互质,求一下方程组的最小整数解
    \\[ \\left\\\\beginarrayllx\\equiv a_1\\mod p_1\\\\x\\equiv a_2\\mod p_2\\\\...\\\\x\\equiv a_k\\mod p_k\\endarray\\right. \\]
    考虑两个式子:\\(x\\equiv a_1 \\mod p_1,x\\equiv a_2\\mod p_2\\)合并(这里是完整的推导过程注意不同部分的模数因为其来源可能不同

    可以合并成:\\(x\\equiv a'\\mod m'\\)。其中\\(a'=p_1[inv(\\fracp_1gcd,\\fracp_2gcd)\\fraca_2-a_1gcd\\%\\fracp_2gcd]+a_1,m'=\\fracp_1p_2gcd\\)\\(gcd=gcd(p_1,p_2),inv(x,y)\\)表示\\(x\\)在模\\(y\\)意义下的逆元,\\(y\\)不一定为质数,所以要用\\(Exgcd\\)求)

    inline int gcd(int x,int b) return b?gcd(b,x%b):x;
    inline int Exgcd(int a,int b,int &x,int &y)
    
      if(!b) x=1,y=0;return a;
      int Gcd=Exgcd(b,a%b,y,x);
      y-=a/b*x;return Gcd;
    
    inline int Inv(int a,int b)int x,y;Exgcd(a,b,x,y);return (x%b+b)%b;
    signed main()
      int Jud=0;n=read();
      for(int i=1;i<=n;i++) p[i]=read(),a[i]=read();
      for(int i=2;i<=n;i++)
      
          int Gcd=gcd(p[i],p[i-1]),Now,p1=p[i-1],p2=p[i],a1=a[i-1],a2=a[i];
          Now=Inv(p1/Gcd,p2/Gcd)%(p2/Gcd);
          Now=(Now*(((a2-a1)/Gcd)%(p2/Gcd))%(p2/Gcd)+(p2/Gcd))%(p2/Gcd);
          Now=((Now%(p2*p1/Gcd)*p1%(p2*p1/Gcd))%(p2*p1/Gcd)+(p2*p1/Gcd))%(p2*p1/Gcd);
          Now=(Now%(p2*p1/Gcd)+a1%(p2*p1/Gcd))%(p2*p1/Gcd);
          p[i]=p2*p1/gcd(p2,p1); a[i]=(Now%p[i]+p[i])%p[i];
      
      print(Jud?-1:a[n]);
    
  • \\(BSGS\\):求\\(A^x\\equiv B\\mod C\\)\\(x\\)。(满足\\(gcd(A,C)=1\\)

    \\(m=\\sqrtC\\),令\\(x=am+b\\),所以有\\(A^am\\equiv A^bB\\mod C\\),预处理\\(A^b\\),暴力枚举\\(a\\)即可。

    int m=sqrt(C)+1,now=1;
    for(int i=0;i<m;i++)mp[(now*B)%C]=i,now=((now%C)*(A%C))%C;
    k=((k%C)*(now%C))%C;
    for(int i=1;i<=m;i++)
    
        if(mp[k]) return ((i%C)*(m%C)-mp[k]+C)%C;
        k=((k%C)*(now%C))%C;
    
  • 扩展\\(BSGS\\):求\\(A^x\\equiv B\\mod C\\)\\(x\\)。(不一定满足\\(gcd(A,C)=1\\)

    \\(d=gcd(A,C)\\),则我们可以除掉\\(d\\),原始变为\\(\\fracAdA^x-1\\equiv \\fracBd\\mod \\fracCd\\),不断检查\\(gcd(\\fraczd,y)\\),一直除到互质为止,最后将减掉的补回来就行了。

    inline int EXBSGS(int A,int B,int C) 
    
      int cnt=0,d,k=1;
      while((d=gcd(A,C))^1)
      
          if(B%d) return -1;
          B/=d;C/=d;++cnt;
          k=(k*(A/d))%C;
          if(k==B) return cnt;
      
      mp.clear();int m=sqrt(C)+1,now=1;
      for(int i=0;i<m;i++) mp[(now*B)%C]=i,now=(now*A)%C;
      k=(k*now)%C;
      for(int i=1;i<=m;i++)
      
          if(mp[k]) return (cnt+i*m-mp[k]+C)%C;
          k=(k*now)%C;
      
      return -1;
    
  • 线性筛:(不多讲,直接上)

    inline void Make_Prime(int T)
    
        Vis[1]=1;
        for(int i=2;i<=T;i++)
        
            if(!Vis[i]) Pri[++Cnt]=i;
            for(int j=1;j<=Cnt&&i*Pri[j]<=T;j++)
            
                Vis[i*Pri[j]]=1;
              if(!(i%Pri[j])) break;
            
        
    
  • \\(Miller\\) \\(Rabin\\)

    前置定理:费马小定理,二次探测:若\\(a^2\\equiv 1\\mod p\\)\\(p\\)为质数,则\\(a\\equiv1\\)\\(p-1\\mod p\\)

    假设我们判定\\(x\\),将其拆为\\(x=2^kt\\)形式,随即一个\\(a\\)并求出\\(a^t\\),然后依次将\\(2\\)乘上去,用二次探测即可。

    最好我们多测几次\\(Miller\\) \\(Rabin\\)

    int Tex[4]=2,3,5,7;
    inline int ksm(int b,int k,int p)
    
      int a=b; k--;
      while(k)
      
          if(k&1) a=(a%p*b%p+p)%p;
          b=(b%p*b%p+p)%p;k>>=1;
      
      return a%p;
    
    inline bool Miller_Rabin(int x)
    
      if(x==1) return 0;
      int Now=x-1,k=0;
      while(!(Now&1)) Now>>=1,k++;
      for(int i=0;i<4;i++)
      
          int a=ksm(Tex[i],Now,x)%x,Nex=a;
          if(x==Tex[i]) return 1;
          for(int j=1;j<=k;j++)
          
              Nex=(a%x*a%x+x)%x;
              if(Nex==1&&a!=1&&a!=x-1) return 0;
              a=Nex;
          
          if(a!=1) return 0;
      
      return 1;
    
  • \\(Lucas\\):懒得证明了,记着:\\(n \\choose m\\%p=n\\%p \\choose m\\%p*n/p \\choose m/p\\%p\\)

    inline int ksm(int b,int k)
    
      int a=b;k--;
      while(k)
      
          if(k&1) a=(a%p*b%p)%p;
          b=(b%p*b%p)%p;k>>=1;
      
      return a%p;
    
    inline int C(int n,int m)
    
      if(m>n) return 0;
      return (Fac[n]%p*ksm((Fac[m]%p*Fac[n-m]%p)%p,p-2)%p)%p;
    
    inline int Lucas(int n,int m)
    
      if(!m) return 1;
      return (C(n%p,m%p)%p*Lucas(n/p,m/p)%p)%p;
    

至此,一些常用的数论基础都在这儿了,还有什么后面再补。

以上是关于数论基础总?结?的主要内容,如果未能解决你的问题,请参考以下文章

基础数论20170529_3 数论_gcd

数论基础

从基础数论函数说起3:莫比乌斯反演

数论总结1(基础数论)

kuangbin带你飞---数论基础

数论 Day2基础归纳法 题目