C++竞赛常用实用代码(2)

欢迎各位读者发评论补充(我会标明补充者的博客和链接)

上一页:C++竞赛常用实用代码

目录

普通判断质数

两数的最大公约数(GCD)

欧拉函数

分解质因数(从欧拉函数中剥离的)

以x为根的树的节点数(邻接表)

扩展欧几里德

十进制数转其他进制

计算组合数C(n,m)

O(m)版

O(logmod)版

O(1)版

求a、mod p的逆元

筛质数

埃筛(O(nlnn))

欧筛(O(n))


更多低级数论代码:https://blog.csdn.net/qq_41814502/article/details/88121632

下一页:C++竞赛常用实用代码(3)

普通判断质数

inline bool is_prime(int n){
    if(n==1||n==0)return 0;
    for(int i=2;i*i<=n;i++)
        if(n%i==0)return 0;
    return 1;
}

两数的最大公约数(GCD)

#define ll long long
inline ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}

欧拉函数

inline int phi(int a){//a的欧拉函数值:小于a且与a互质的数的个数
    int s=a;
    for(int o=2;o*o<=a;o++)
        if(a%o==0){
            s=s/o*(o-1);
            while(a%o==0)a/=o;
        }
    if(a>1)s=s/a*(a-1);
    return s;
}

分解质因数(从欧拉函数中剥离的)

inline void prime_work(int a){
    for(int o=2;o*o<=a;o++)
        if(a%o==0){
            prime[++len]=o;
            while(a%o==0)num[len]++,a/=o;
        }
    if(a>1)prime[++len]=x,num[len]=1;
}

以x为根的树的节点数(邻接表)

//普通:
int dfs(int x){
    int u=G[x].size(),Sum=1;
    for(int i=0;i<u;i++)
        Sum+=dfs(G[x][i]);
    return Sum;
}
//记忆化(用a数组保存):
int dfs(int x){
    if(a[x])return a[x];
    a[x]=1;
    int u=G[x].size();
    for(int i=0;i<u;i++)
        a[x]+=dfs(G[x][i]);
    return a[x];
}

扩展欧几里德

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

十进制数转其他进制

//将十进制x转换为d进制并输出
void Ten(int x,int d)//2≤d≤10
{
	int i,n=0,h=1;
	int s[32]={0};//可以换成全局数组保存结果
	if(x<0)
	{
		x*=-1;
		h=-1;
	}
	while(x>=d)
	{
		s[n++]=x%d;
		x/=d;
	}
	s[n]=x;
	if(h==-1)
		putchar('-');
	for(i=n;i>=0;i--)
		putchar(s[i]+'0');
}

计算组合数C(n,m)

O(m)版

inline int C(int n,int m){
    int k=1;
    if(m<n){
        if(m<n-1)
            for(int i=1,j=n-m+1;i<=m;i++,j++)
                k=k*j/i;
        else k=n;
    }
    return k;
}

O(logmod)版

#define ll long long
inline ll ksm(ll a,ll b){//快速幂
    ll res=1;
    for(;b;b>>=1){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
    }
    return res;
}
inline void prepare(){
    jc[0]=jc[1]=1;
    for(int i=2;i<=MAXN;i++)jc[i]=jc[i-1]*i%mod;
}
inline ll C(int n,int m){//阶乘数组jc要预处理↑
	if(m>n)return 0;
	return jc[n]*ksm(jc[m],mod-2)%mod*ksm(jc[n-m],mod-2)%mod;
}//前提是mod得是个质数(一般给的都是1e9+7)

O(1)版

1.(结合分数结构体

#define ll long long
inline void prepare(){//阶乘预处理 
    jc[0]=jc[1]=1;
    for(int i=2;i<=MAXN;i++)jc[i]=jc[i-1]*i%mod;
}
inline ll C(ll n,ll m){
	if(m>n)return 0;
	return Q(jc[n],jc[m]*jc[n-m]%mod);
}

2.预处理逆元

#define ll long long
inline ll ksm(ll a,ll b){
	ll res=1;
	for(;b;b>>=1){
		if(b&1)res=res*a%mod;
		a=a*a%mod;
	}
	return res;
}
inline void prepare(){//阶乘、逆元预处理,inv[i]表示i!的逆元
	fac[0]=fac[1]=inv[0]=1;
	for(int i=2;i<=MAXN;i++)fac[i]=fac[i-1]*i%mod;
	inv[MAXN]=ksm(fac[MAXN],mod-2);
	for(int i=MAXN-1;i>0;i--)inv[i]=inv[i+1]*(i+1)%mod;
}
inline ll C(int n,int m){
	if(m>n)return 0;
	return fac[n]*inv[m]%mod*inv[n-m]%mod;
}

求a、mod p的逆元

inline int niyuan(int a,int p){
	int phi=p,x=p;//欧拉函数begin
	for(int i=2;i<=x;i++)
		if(x%i==0){phi-=phi/i;while(x%i==0)x/=i;}
	if(x>1)phi-=phi/x;//欧拉函数end
	phi--;
	int ans=1;//快速幂begin
    for(;phi;phi>>=1){
		if(phi&1)ans=ans*a%p;
		a=a*a%p;
	}//快速幂end
	return ans;
}

筛质数

埃筛(O(nlnn))

//bool nop[MAXN+5];
nop[0]=nop[1]=1;
for(int i=2;i<=MAXN;i++)
	if(!nop[i])
		for(int j=(i<<1);j<=MAXN;j+=i)
			nop[j]=1;

欧筛(O(n))

//bool nop[MAXN+5];
//vector<int>pr;
nop[0]=nop[1]=1;
for(int a=2;a<=MAXN;a++){
	if(!nop[a])pr.push_back(a);
	for(int i=0;i<pr.size();i++){
		if(pr[i]*a>MAXN)break;
		nop[a*pr[i]]=1;
		if(a%pr[i]==0)break;
	}
}

欢迎各位读者发评论补充~

猜你喜欢

转载自blog.csdn.net/weixin_43960287/article/details/87555268