数论整理(代码篇)
理论方面的内容参见数论整理(理论篇)
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;
}

                
            
        
浙公网安备 33010602011771号