zoukankan      html  css  js  c++  java
  • 基础数论模板题总结

    一、法雷序列(莫比乌斯反演/欧拉函数前缀和)

    莫比乌斯反演:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    int p[1000010],vis[1000010],mu[1000100],cnt;
     
    void get()
    {
        memset(vis,0,sizeof(vis));
        cnt=0;
        vis[1]=1;
        mu[1]=1;
        for(int i=2; i<=1000000; i++)
        {
            if(!vis[i])
            {
                p[cnt++]=i;
                mu[i]=-1;
            }
            for(int j=0; j<cnt; j++)
            {
                if(p[j]*i>1000000)
                {
                    break;
                }
                vis[i*p[j]]=1;
                if(i%p[j]==0)
                {
                    mu[i*p[j]]=0;
                    break;
                }
                else
                {
                    mu[i*p[j]]=-mu[i];
                }
            }
        }
    }
     
    int main()
    {
        int a,b,c,d,k,n;
        get();
        scanf("%d",&n);
        a=1;
        b=1;
        b=n;
        d=n;
        k=1;
        if(b>d)
        {
            swap(b,d);
        }
        long long ans1=0;
        for(int i=1; i<=b; i++)
        {
            ans1+=(long long)mu[i]*(b/i)*(d/i);
        }
        long long ans2=0;
        for(int i=1; i<=b; i++)
        {
            ans2+=(long long)mu[i]*(b/i)*(b/i);
        }
        ans1-=ans2/2;
        printf("%lld
    ",ans1-1);
    }

    欧拉函数前缀和:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    int vis[1000010],prime[1000010],phi[1000010],t,n;
    long long sum[1000010];
     
    void get()
    {
        for(int i=2;i<=1000000;i++)
        {
            if(!vis[i])
            {
                prime[++t]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=t;j++)
            {
                if(prime[j]*i>1000000)
                {
                    break;
                }
                vis[prime[j]*i]=1;
                phi[prime[j]*i]=phi[i]*(prime[j]-1);
                if(i%prime[j]==0)
                {
                    phi[prime[j]*i]=phi[i]*prime[j];
                    break;
                }
            }
        }
    }
     
    int main()
    {
        get();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            sum[i]=sum[i-1]+phi[i]*1ll;
        }
        printf("%lld
    ",sum[n]);
    }

    二、组合数取模(线性求模数阶乘,阶乘逆元)

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define int long long
    using namespace std;
     
    int mod,fac[100010],inv[100010],n,m;
     
    int kasumi(int a,int b)
    {
        int ans=1;
        while(b)
        {
            if(b&1)
            {
                ans=((ans%mod)*a)%mod;
            }
            a=((a%mod)*a)%mod;
            b>>=1;
        }
        return ans;
    }
     
    signed main()
    {
        scanf("%lld%lld%lld",&m,&n,&mod);
        fac[1]=1;
        int lim=min(mod-1,100000ll);
        for(int i=2;i<=lim;i++)
        {
            fac[i]=(fac[i-1]%mod)*i%mod;
        }
        inv[lim]=kasumi(fac[lim],mod-2);
        for(int i=lim-1;i>=1;i--)
        {
            inv[i]=((inv[i+1]%mod)*(i+1))%mod;
        }
        printf("%lld
    ",((fac[m]*inv[n])%mod*inv[m-n])%mod);
    }

    三、乘法逆元(扩展欧几里得)

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    long long a,c;
     
    long long gcd(long long a,long long b)
    {
        if(a%b==0)
        {
            return b;
        }
        return gcd(b,a%b);
    }
     
    void exgcd(long long a,long long b,long long &x,long long &y)
    {
        if(b==0)
        {
            x=1;
            y=0;
            return ;
        }
        exgcd(b,a%b,x,y);
        int tmp=x;
        x=y;
        y=tmp-a/b*y;
    }
     
    int main()
    {
        scanf("%lld%lld",&a,&c);
        long long x,y;
        if(gcd(a,c)!=1)
        {
            puts("-1");
            return 0;
        }
        exgcd(a,c,x,y);
        if(x<0)
        {
            while(x<0) x+=c;
        }
        printf("%lld
    ",x);
    }

    四、素数个数和(线性筛素数)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    int prime[10000010],vis[10000010],cnt,n;
     
    void get(int n)
    {
        for(int i=2;i<=n;i++)
        {
            if(!vis[i])
            {
                prime[++cnt]=i;
            }
            for(int j=1;j<=cnt;j++)
            {
                if(prime[j]*i>n)
                {
                    break;
                }
                vis[prime[j]*i]=1;
                if(i%prime[j]==0)
                {
                    break;
                }
            }
        }
    }
     
    int main()
    {
        scanf("%d",&n);
        get(n);
        printf("%d
    ",cnt);
    }

    五、大数求欧拉函数(sqrt(n)暴力)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 100000
    using namespace std;
     
    long long n,prime[100010],vis[100010],cnt;
     
    int check(long long x)
    {
        for(int i=2;i*i<=x;i++)
        {
            if(x%i==0)
            {
                return 0;
            }
        }
        return 1;
    }
     
    long long get_phi(long long x)
    {
        long long ans=x;
        if(check(x))
        {
            ans=ans/x*(x+1);
        }
        for(int i=2;i*i<=x;i++)
        {
            if(x%i==0)
            {
                if(check(i))
                {
                    ans=ans/i*(i-1);
                }
                if(check(x/i)&&x/i!=i)
                {
                    ans=ans/(x/i)*(x/i-1);
                }
            }
        }
        return ans;
    }
     
    int main()
    {
        scanf("%lld",&n);
        n==1?puts("1"):printf("%lld
    ",get_phi(n));
    }

    六、网格的走法(卡特兰数)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mod 1000000007
    using namespace std;
      
    long long fac[200010],inv[200010],n;
     
    long long kasumi(long long a,long long b)
    {
        long long ans=1;
        while(b)
        {
            if(b&1)
            {
                ans=ans*a%mod;
            }
            a=a*a%mod;
            b>>=1;
        }
        return ans;
    }
     
    int main()
    {
        scanf("%lld",&n);
        fac[1]=1;
        for(int i=2;i<=2*n;i++)
        {
            fac[i]=fac[i-1]*i%mod;
        }
        inv[2*n]=kasumi(fac[2*n],mod-2);
        for(int i=2*n-1;i>=1;i--)
        {
            inv[i]=inv[i+1]*(i+1)%mod;
        }
        printf("%lld
    ",((fac[2*n]*inv[n])%mod*inv[n+1])%mod);
    }

    七、又一个小球问题(第一类斯特林数)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mod 1000000007
    using namespace std;
     
    long long f[1010][1010],n,m;
     
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            f[i][0]=0ll;
            f[i][i]=1ll;
        }
        f[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                f[i][j]=f[i-1][j-1]+f[i-1][j]*1ll*(i-1);
                f[i][j]%=mod;
            }
        }
        printf("%lld
    ",f[n][m]);
    }

    八、叕一个小球问题(第二类斯特林数)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mod 1000000007
    using namespace std;
     
    long long f[1010][1010],n,m;
     
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            f[i][0]=0ll;
            f[i][i]=1ll;
        }
        f[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                f[i][j]=f[i-1][j-1]+f[i-1][j]*1ll*j;
                f[i][j]%=mod;
            }
        }
        printf("%lld
    ",f[n][m]);
    }
  • 相关阅读:
    如何将你的AIR程序正常显示在iPhone5上?
    升级Flash Builder 4.7中的AIR SDK
    Flex AIR加载时全屏显示
    在Mac系统的安装Flash Builder 4.7开发工具
    What's XPath?
    XPath节点
    What's XML?
    65个源码下载网站
    [导入]轻松掌握Ajax.net系列教程
    MemberShip 示例
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9291699.html
Copyright © 2011-2022 走看看