• 数论整理(代码篇)


    理论方面的内容参见数论整理(理论篇)

    1. 快速幂\(O(\log b)\)

    其实这个不应该算数论?

    //递归实现
    long long qpow(long long a,long long b,long long mod)
    {
          if(b==0)return 1;
          long long ans=qpow(a,b/2,mod);
          ans=(ans*ans)%mod;
          if(b&1)ans=(a%mod*ans)%mod;
          return ans;
    }
    //迭代实现
    long long qpow(long long a,long long b,long long mod)
    {
        long long ans=1,now=a;
        while(b>0)
        {
            if(b&1)ans*=now,ans%=mod;
            now*=now,now%=mod;
            b>>=1;
        }
        return ans;
    }
    

    2. 最大公因数&最小公倍数\(O(\log \max(a,b))\)

    int gcd(int a,int b)
    {
    	if(b==0)return a;
    	else return gcd(b,a%b);
    }
    int lcm(int a,int b)
    {
        return a/gcd(a,b)*b;
    }
    

    3. 质数

    1. \(O(\sqrt{n})\)判断单个数是否是质数

    bool isprime(int xx)
    {
    	if(xx<2)return 0;
    	int limit=sqrt(xx);
    	for(int i=2;i<=limit;++i)
    		if(xx%i==0)
    			return 0;
    	return 1;
    }
    

    2. \(O(n)\)线性筛质数

    int v[1000010],prime[1000010];
    void linearprime(int n)
    {
    	memset(v,0,sizeof(v));
    	int cnt=0;
    	for(int i=2;i<=n;i++)
    	{
    		if(v[i]==0)
    		{
    			v[i]=i;
    			prime[++cnt]=i;
    		}
    		for(int j=1;j<=cnt;j++)
    		{
    			if(prime[j]>v[i]||prime[j]>n/i)break;
    			v[i*prime[j]]=prime[j];
    		}
    	}
    	return;
    }
    

    3. Miller-Rabin 判素

    4. \(O(\sqrt{n})\)分解质因数

    int mp[1000010];
    void factorization(int xx)
    {
    	if(xx<2)return;
    	int limit=sqrt(xx);
    	for(int i=2;i<=limit;i++)
    		while(xx%i==0)
    		{
    			mp[i]++;
    			xx/=i;
    			if(xx==1)return;
    		}
    	if(xx>1)mp[xx]++;
    	return;
    }
    

    5. Pollard-Rho 分解质因数

    5. 扩展欧几里得\(O(\log \max(a,b))\)

    1. 板子

    void exgcd(int a,int b,int &x,int &y)
    {
    	if(!b){x=1;y=0;return;}
    	exgcd(b,a%b,y,x);
    	y-=a/b*x;
    	return;
    }
    

    2. 解形如\(ax+by=c\)的二元一次不定方程

    6. 乘法逆元

    1. 单个数求逆元\(O(\log \max(a,b))\)

    int getinv(int a,int b)
    {
    	int x,y;
    	exgcd(a,b,x,y);
    	return (x+b)%b;
    }
    

    2. \(O(n)\)\(1,2,...,n\mod p\)的逆元

    int inv[10000010];
    void linearinv(int n,int p)
    {
    	inv[1]=1;
    	for(int i=2;i<=n;i++)inv[i]=(long long)(p-p/i)*inv[p%i]%p;
    	return;
    }
    

    3. \(O(a+\log b)\)\(1!,2!,...,a!\mod b\)的逆元

    int facinv[10000010];
    void getfacinv(int a,int b)
    {
    	int now=1;
    	for(int i=1;i<=a;i++)now=now*i%b;
    	facinv[a]=getinv(now,b);
    	for(int i=a-1;i>=1;i--)facinv[i]=facinv[i+1]*(i+1)%b;
    	return;
    }
    

    7. 欧拉函数

    1. 求单个\(\varphi (n)\quad O(\sqrt{n})\)

    int geteuler(int n)
    {
    	if(n==1)return 0;
     	int limit=sqrt(n),ans=n;
    	for(int i=2;i<=limit;i++)
    		if(n%i==0)
    		{
    			ans-=ans/i;
    			while(n%i==0)n/=i;
    		}
    	if(n>1)ans-=ans/n;
    	return ans;
    }
    

    2. \(O(n)\)\(\varphi (1),\varphi (2),...,\varphi (n)\)

    int v[1000010],prime[1000010],phi[1000010];
    void lineareuler(int n)
    {
            memset(v,0,sizeof(v));
    	int cnt=0;
    	for(int i=2;i<=n;i++)
    	{
    		if(v[i]==0)
    		{
    			v[i]=i;
    			prime[++cnt]=i;
    			phi[i]=i-1;
    		}
    		for(int j=1;j<=cnt;j++)
    		{
    			if(prime[j]>v[i]||prime[j]>n/i)break;
    			v[i*prime[j]]=prime[j];
    			phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]);
    		}
    	}
    	return;
    }
    

    8. CRT&exCRT

    1. CRT

    int crt()
    {
    	int mul=1ll,ans=0;
    	for(int i=1;i<=n;i++)mul*=a[i];
    	for(int i=1;i<=n;i++)
    	{
    		int now=mul/a[i];
    		ans=(ans+now*inv(now,a[i])*b[i])%mul;
    	}
    	return (ans+mul)%mul;
    }
    

    2.exCRT

    p.s. luogu的exCRT模板太过毒瘤,请使用光速乘

    所有的int请自动理解为long long

    int n,ans,lc=1,a[100010],b[100010];
    inline int excrt()
    {
        int p,q,g,now,m;
        for(int i=1;i<=n;i++)
        {
            exgcd(lc,a[i],p,q);
            now=((b[i]-ans)%a[i]+a[i])%a[i];
            g=gcd(lc,a[i]),m=a[i]/g;
            if(now%g)return -1;
            p=mul(now/g,p,m);
            q=lc,lc*=m;
            ans=(ans+mul(p,q,lc))%lc;
        }
        return ans;
    }
    

    9. Lucas&exLucas

    虽然这两个东西是用来求组合数的,但鉴于具体计算还是与数论有关就放到这里了(

    1. Lucas

    int facs[100010];
    int c(int n,int m,int p)
    {
        if(n>m)return 0;
        return (qpow(facs[m-n],p-2,p)*qpow(facs[n],p-2,p)%p*facs[m])%p;
    }
    int lucas(int n,int m,int p)
    {
        if(m==0)return 1;
        return c(n%p,m%p,p)*lucas(n/p,m/p,p)%p;
    }
    

    2. exLucas

    10. BSGS&exBSGS

    1. BSGS

    2. exBSGS

  • 相关阅读:
    hdu 2199 Can you solve this equation? 二分
    STL 学习代码~
    hdu 1551 Cable master 二分
    fzu 1564 Combination 组合数是否包含因数
    fafu 1079 帮冬儿忙 组合数包含因数个数
    soj 3290 Distribute The Apples I 组合数对素数取余
    fzu 2020 组合 组合数对素数取余
    hdu 1969 Pie 二分
    hdu 2141 Can you find it? 二分
    hdu 2899 Strange fuction 二分
  • 原文地址:https://www.cnblogs.com/pjykk/p/11223178.html
Copyright © 2020-2023  润新知