zoukankan      html  css  js  c++  java
  • Thematic001.数论专题

    目录

    • 素数
    • 欧拉函数
    • 约数
    • 乘法逆元
    • 欧几里得(拓展)
    • 中国剩余定理
    • 中国剩余定理(拓展)
    • BSGS
    • BSGS(拓展)

    素数

    例题

    暴力 ((O(nsqrt{n}))

    bool Prime[MAXN];
    
    void Check(int n)
      {
        for (int i=1;i<=n;i++)
          {
            if (i<2) continue;
            if (i==2||i==3)
              {
                Prime[i]=true;
                continue;
              }
            for (int j=2;j<=ceil(sqrt(i));j++) if (i%j==0)
              {
                Prime[i]=true;
                break;
              }
            Prime[i]=!Prime[i];
          }
      }
    

    埃式筛法 ((O(nlog n))

    bool vis[MAXN];
    int size,prime[MAXN];
    
    void FindPrime(int n)
      {
        vis[0]=vis[1]=true;
        for (int i=2;i<=n;i++) if (!vis[i])
          {
            prime[++size]=i;
            for (int j=2;i*j<=n;j++) vis[i*j]=true;
          }
      }
    

    欧拉筛法 ((O(n))

    bool vis[MAXN];
    int size,prime[MAXN];
    
    void FindPrime(int n)
      {
        vis[0]=vis[1]=true;
        for (int i=2;i<=n;i++)
          {
            if (!vis[i]) prime[++size]=i;
            for (int j=1;j<=size&&i*prime[j]<=n;j++)
              {
                vis[i*prime[j]]=true;
                if (i%prime[j]==0) break;
              }
          }
      }
    

    欧拉函数

    直接求 (phi) ((n)) ((O(sqrt{n}))

    int FindPhi(int n)
      {
        int ans=n;
        for (int i=2;i*i<=n;i++)
          {
            if (n%i==0)
              {
                ans-=ans/i;
                while (n%i==0) n/=i;
              }
          }
        if (n>1) ans-=ans/n;
        return ans;
      }
    

    同时求 (phi) ((1)) 到 (phi) ((n))时与 (1)(n) 的素数 ((O(n))

    bool vis[MAXN];
    int size,Prime[MAXN],Phi[MAXN];
    
    void Find_Phi_and_Prime(int n)  
      {  
        for (int i=2;i<n;i++)  
          {  
            if (!vis[i])  
              {  
                Prime[++size]=i;  
                Phi[i]=i-1;  
              }  
            for (int j=1;j<=size&&i*Prime[j]<n;j++)  
              {  
                vis[i*Prime[j]]=true;  
                if (i%Prime[j]==0)  
                  {  
                    Phi[i*Prime[j]]=Phi[i]*Prime[j];  
                    break;  
                  }  
                else Phi[i*Prime[j]]=Phi[i]*(Prime[j]-1);
              }  
          }  
      } 
    

    约数

    例题

    辗转相除法

    int GCD(int a,int b)
      {
        if (b==0) return a;
        return GCD(b,a%b);
      }
    

    二进制算法

    • 低精

    int GCD(int x,int y)
      {
        int i,j;
        if (x==0) return y;
        if (y==0) return x;
        for (i=0;(x&1)==0;i++) x>>=1;
        for (j=0;(y&1)==0;j++) y>>=1;
        if (j<i) i=j;
        while (1)
          {
            if (x<y) x^=y,y^=x,x^=y;
            if ((x-=y)==0) return y<<i;
            while ((x&1)==0) x>>=1;
          }
      }
    
    • 高精

    #include <bits/stdc++.h>
    using namespace std;
    
    struct Data
      {
        int a[2005];
        int num;
      };
    char c[10005];
    
    void div2(Data &x)
      {
        if (x.a[x.num]==1)
          {
            x.a[x.num-1]+=10000000;
            x.num--;
          }
        for (int i=x.num;i>=1;i--)
          {
            if (x.a[i]&1) x.a[i-1]+=10000000;
            x.a[i]>>=1;
          }
      }
    
    void plus2(Data &x)
      {
        for (int i=1;i<=x.num;i++) x.a[i]<<=1;
        for (int i=1;i<x.num;i++)
          {
            if (x.a[i]>=10000000)
              {
                x.a[i]-=10000000;
                x.a[i+1]++;
              }
          }
        if (x.a[x.num]>=10000000)
          {
            x.a[x.num]-=10000000;
            x.a[x.num+1]=1;
            x.num++;
          }
      }
    
    void sub(Data &x,Data y)
      {
        for (int i=1;i<=y.num;i++) x.a[i]-=y.a[i];
        for (int i=1;i<x.num;i++)
          {
            if (x.a[i]<0)
              {
                x.a[i+1]--;
                x.a[i]+=10000000;
              }
          }
        if (x.a[x.num]==0) x.num--;
      }
    
    bool comp(Data &x,Data &y)
      {
        if (x.num>y.num) return false;
        if (x.num<y.num)
          {
            swap(x.num,y.num);
            for (int i=1;i<=max(x.num,y.num);i++) swap(x.a[i],y.a[i]);
            return false;
          }
        for (int i=x.num;i>=1;i--)
          {
            if (x.a[i]>y.a[i]) return false;
            if (x.a[i]<y.a[i])
              {
                swap(x.num,y.num);
                for (int i=1;i<=max(x.num,y.num);i++) swap(x.a[i],y.a[i]);
                return false;
              }
          }
        return true;
      }
    
    int main()
      {
        Data n,m;
        int stop,x,y,t,cnt;
        scanf("%s",c);
        for (int i=strlen(c)-1;i>=0;i-=7)
          {
            n.num++;
            n.a[n.num]=0;
            stop=max(i-6,0);
            for (int j=i;j>=stop;j--) n.a[n.num]+=(c[j]-'0')*pow(10,i-j);
          }
        scanf("%s",c);
        for (int i=strlen(c)-1;i>=0;i-=7)
          {
            m.num++;
            m.a[m.num]=0;
            stop=max(i-6,0);
            for (int j=i;j>=stop;j--) m.a[m.num]+=(c[j]-'0')*pow(10,i-j);
          }
        for (x=0;!(n.a[1]&1);x++) div2(n);
        for (y=0;!(m.a[1]&1);y++) div2(m);
        if (y<x) x=y;
        while (1)
          {
            if (comp(n,m)) 
              {
                while(x--) plus2(n);
                printf("%d",n.a[n.num]);
                for (int i=n.num-1;i>=1;i--)
                  {
                    t=n.a[i];
                    cnt=0;
                    while (t/10) t/=10,cnt++;
                    for (int i=1;i<7-cnt;i++) printf("0");
                    printf("%d",n.a[i]);
                  }
                return 0;
              }
            sub(n,m);
            while (!(n.a[1]&1)) div2(n);
          }
        return 0;
      }
    

    乘法逆元

    例题

    代码

    • 欧几里得(拓展)

    long long exgcd(long long a,long long b,long long &x,long long &y)
      {
        if (b==0)
          {
            x=1,y=0;
            return a;
          }
        long long r=exgcd(b,a%b,x,y);
        long long t=x;
        x=y;
        y=t-(a/b)*y;
        return r;
      }
    
    • 快速幂

    long long fastpow(long long a,long long b,long long p) //a^b%p
      {
        if (b==0) return 1;
        if (b==1) return a%p;
        long long half=fastpow(a,b/2,p);
        if (b&1) return ((half%p*half%p)%p*a)%p;
        return (half%p*half%p)%p;
      }
      
    int main()
      {
        //...
        long long x=fastpow(a,b-2,b);
        //...
      }
    
    • 线性算法求 (1)(n)(b) 的逆元 ((O(n))

    inv[1]=1;
    for (int i=2;i<=n;i++)
        inv[i]=(p-p/i)*inv[p%i]%p;
    

    欧几里得(拓展)

    代码

    long long exGCD(long long a,long long b,long long &x,long long &y)
      {
        if (b==0)
          {
            x=1,y=0;
            return a;
          }
        long long r=exGCD(b,a%b,x,y);
        long long t=x;
        x=y;
        y=t-(a/b)*y;
        return r;
      }
    

    中国剩余定理

    例题

    代码

    long long CRT(void)
      {
        long long M=1,ans=0;
        for (int i=1;i<=n;i++) M*=m[i];
        for (int i=1;i<=n;i++)
          {
            long long tM=M/m[i];
            long long x,y;
            exgcd(tM,m[i],x,y);
            ans=(ans+tM*x*a[i])%M;
          }
        return (ans+M)%M;
      }
    

    中国剩余定理(拓展)

    例题

    代码

    long long exCRT(void)
      {
        long long M=m[1],ans=b[1],x,y,g,t,k1;
        for (int i=2;i<=n;i++)
          {
            g=exgcd(M,m[i],x,y);
            if ((b[i]-ans)%g) return -1;
            k1=x*(b[i]-ans)/g;
            t=m[i]/g;
            x=(k1%t+t)%t;
            ans=M*x+ans;
            M=M/g*m[i];
          }
        return (ans%M+M)%M;
      }
    

    BSGS

    例题

    代码

    long long BSGS(long long a,long long b,long long p)
      {
        a%=p,b%=p;
        if (a==0)
          {
            if (b==0) return 0;
            return -1;
          }
        map <long long,long long> M;
        M.clear();
        long long temp=b,m=ceil(sqrt(p));
        for (int i=0;i<=m;i++,temp=temp*a%p) M[temp]=i;
        temp=a=fastpow(a,m,p);
        for (int i=1;i<=m;i++,temp=temp*a%p) if (M.count(temp)) return i*m-M[temp];
        return -1;
      }
    

    BSGS(拓展)

    例题

    代码

    long long inv(long long a,long long p)
      {
        long long x,y,ans;
        exgcd(a,p,x,y);
        return (x%p+p)%p;
      }
    
    long long exBSGS(long long a,long long b,long long p)
      {
        if (b==1||p==1) return 0;
        long long x,y,g,k=0,na=1;
        while (g=exgcd(a,p,x,y))
          {
            if (g==1) break;
            if (b%g) return -1;
            k++;
            b/=g;
            p/=g;
            na=na*(a/g)%p;
            if (na==b) return k;
          }
        long long ans=BSGS(a,b*inv(na,p)%p,p);
        if (ans==-1) return -1;
        return ans+k;
      }
    
  • 相关阅读:
    [笔记]--Sublime Text 配置及使用技巧
    [笔记]--Oracle 10g在Windows 32位系统使用2G以上内存
    [笔记]--Ubuntu安装Sublime Text 2
    [笔记]--Oracle修改SGA大小
    [转载]--Ubuntu下修改DNS重启也能用的方法
    [转载]--用Python 自动安装软件
    谈谈-EventBus的使用
    谈谈-ListView的优化
    谈谈-View的事件分发机制
    谈谈-ScrollView嵌套ListView
  • 原文地址:https://www.cnblogs.com/666DHG/p/Thematic001.html
Copyright © 2011-2022 走看看