• 数论模板


    一.欧拉筛求素数

    for (int i = 2; i <= n; i++)
    	{
    		if (!pri[i])
    			ans[++tot] = i;
    		for (int j = 1; (j <= tot) && (i * ans[j] <= n); j++)
    		{
    			pri[i * ans[j]] = 1;
    			if (i % ans[j] == 0)
    				break;
    		}
    	}
    

    二.欧拉函数

    #include <bits/stdc++.h>
    #define ll long long
    const int N = 1e5 + 5;
    
    ll read()
    {
    	ll x=0;int f=1;char ch=getchar();
    	while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    	while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    int phi[N],p[N],cnt,E[N],pri[N];
    int getphi(int n)//针对一个数求欧拉函数
                    //原理:φ(n)=n*(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/p4)……(1-1/pn)
    {
        int ans=n;
        for (int i=2;i*i<=n;i++)
        {
            if (n%i==0)
            {
                ans=ans/i*(i-1);
                while (n%i==0) n/=i;
            }
        }
        if (n) ans=ans/n*(n-1);
        return ans;
    }
    
    int getphi2(int n)//打表,但较为暴力
    {
        for (int i=2;i<=n;i++)
        {
            if (!E[i])
            {
                for (int j=i;j<=n;j+=i)
                {
                    if (!E[j]) E[j]=j;
                    E[j]=E[j]/i*(i-1);
                }
            }
        }
        return E[n];
    }
    
    int getphi3(int n)//用欧拉筛法同时求出素数和欧拉函数
        //若a为素数,b%a==0,phi[a*b]=phi[b]*a
    {
        phi[1]=1;
        for (int i=2;i<=n;i++)
        {
            if (!pri[i])//是素数
            {
                p[++cnt]=i;
                phi[i]=i-1;
            }
            for (int j=1;j<=cnt&&p[j]*i<=n;j++)
            {
                pri[p[j]*i]=1;
                if (i%p[j]==0)
                {
                    phi[i*p[j]]=phi[i]*p[j];
                    break;
                }
                else phi[i*p[j]]=phi[i]*(p[j]-1);//a,b互质,欧拉函数为积性函数,phi[a*b]=phi[a]*phi[b]
            }
        }
        return phi[n];
    }
    int main()
    {
        int n=read();
        int a=getphi(n);
        int b=getphi2(n);
        int c=getphi3(n);
        printf("%d %d %d",a,b,c);
        return 0;
    }
    

    三,快速幂

    ll b,n,k,ans=1;
    int main()
    {
    	b=read();n=read();k=read();
    	b%=k;
    	while(n)
    	{
    		if(n&1)ans=(ans*b)%k;
    		n>>=1;
    		b=(b*b)%k;
    	}
    	printf("%I64d",ans);
    	return 0;
    }
    

    四,逆元

    1. 费马小定理求逆元
    ll qpow(ll a, ll b)
    {
        ll res = 1;
        while (b)
        {
            if (b & 1)
                res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res % mod;
    }
    // 费马小定理 —— a在模p意义下的逆元
    ll Inv(ll a, ll p) { return qpow(a, p - 2); }
    

    2.扩展欧几里得求逆元

    typedef long long ll;
    ll exgcd(ll a, ll b, ll &x, ll &y) //扩展欧几里得算法
    {
        if (b == 0)
        {
            x = 1, y = 0;
            return a;
        }
        ll t = exgcd(b, a % b, x, y);
        ll tmp = x;
        x = y;
        y = tmp - a / b * x;
        return t;
    }
    ll Inv(int a, int mod) //求a在mod下的逆元,不存在逆元返回-1
    {
        ll x, y;
        ll d = exgcd(a, mod, x, y);
        return d == 1 ? (x%mod+ mod) % mod : -1; //x可能是负数,转化成正数
    }
    

    五,中国剩余定理

    #include<bits/stdc++.h>
    #define inf 1000000000
    #define ll long long
    #define N 500010
    #define lson rt<<1
    #define rson rt<<1|1
    #define mo 999911659
    using namespace std;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int n;
    ll x,y,yu[20],pri[20],M=1,ans;
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
    	if (b==0) {x=1,y=0;return a;}
    	ll g=exgcd(b,a%b,x,y);
    	int t=x;x=y;y=t-a/b*y;
    	return g;
    }
    int main()
    {
    	int n=read();
    	for (int i=1;i<=n;i++) 
    	{
    		pri[i]=read();M*=pri[i];
    		yu[i]=read();
    	}
    	for (int i=1;i<=n;i++)
    	{
    		ll tmp=M/pri[i];
    		exgcd(tmp,pri[i],x,y);
    		ans=(ans+yu[i]*tmp*x+M)%M;
    	}
    	printf("%lld",(ans+M)%M);
    	return 0;
    }
    

    六,Lucas定理

    #include<bits/stdc++.h>//求C(n+m,m)
    using namespace std;
    #define re register int
    #define ull unsigned long long
    #define ll long long
    #define INF 0x3f3f3f3f
    #define N 200009
    #define lson rt<<1
    #define rson rt<<1|1
    #define ne e[i].to
    #define mo 998244353
    #define lowbit(x) (x)&(-(x))
    void FRE(){freopen("journalist.in","r",stdin);freopen("journalist.out","w",stdout);}
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ll)(ch-'0');ch=getchar();}
        return x*f;
    }
    typedef pair<int,ll>P;
    int n,m,p;
    ll fac[100010];
    ll ksm(ll a,int b)
    {
    	ll res=1;
    	while (b)
    	{
    		if (b&1) res=res*a%p;
    		a=a*a%p;
    		b>>=1;
    	}
    	return res;
    }
    ll cal(int a,int b)
    {
    	if (a<b) return 0;if (!b) return 1;
    	return fac[a]*ksm(fac[b],p-2)%p*ksm(fac[a-b],p-2)%p;
    }
    ll lucas(int x,int y)
    {
    	if (!y) return 1;if (x<y) return 0;
    	return lucas(x/p,y/p)*cal(x%p,y%p)%p;
    }
    int main()
    {
    	int T=read();
    	while (T--)
    	{
    		n=read(),m=read(),p=read();
    		fac[0]=1;
    		for (int i=1;i<=100003;i++) fac[i]=fac[i-1]*i%p;	
    		printf("%lld
    ",lucas(n+m,m));
    	}
    	return 0;
    }
    
  • 相关阅读:
    连续奇数
    50:数根
    38:花生采摘
    素数对
    17:字符串判等
    2702:密码翻译
    27:单词翻转
    15:整理药名
    12:加密的病历单
    09:密码翻译
  • 原文地址:https://www.cnblogs.com/71-111/p/14634314.html
Copyright © 2020-2023  润新知