Loading

数论整理(代码篇)

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

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

posted @ 2019-07-21 22:39  pjykk  阅读(189)  评论(0编辑  收藏  举报