欢迎各位读者发评论补充(我会标明补充者的博客和链接)
上一页:C++竞赛常用实用代码
目录
更多低级数论代码: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?a:gcd(b,a%b);}
欧拉函数
inline int getphi(int x){//x的欧拉函数值:1~x中与x的最大公因数为1的数的个数
int r=x;
for(int i=2;i*i<=x;i++)
if(x%i==0){r-=r/i;while(x%i==0)x/=i;}
if(x>1)r-=r/x;
return r;
}
分解质因数(从欧拉函数中剥离的)
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(n log log n))
//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;
}
}
欢迎各位读者发评论补充~