CSP-S可能出现的模板(手抄版)
CSP-S rp+++++++++++
前排提示,本篇文章带有注释~
数学
快速幂
int ksm(int a,int b,int p){
int ret=1;
while(b){
if(b&1)ret=(ret*a)%p;
a=(a*a)%p;
b=b>>1;
}
return ret;
}
//b按位枚举 如果该位为1额外乘上a 每次a乘方
Lucas
int init(int a,int b){
ny[1]=1;
for(int i=2;i<N;i++)ny[i]=(mod-mod/i)*ny[mod%i]%mod;
jcny[0]=jcny[1]=1;
for(int i=2;i<N;i++)jcny[i]=jcny[i-1]*ny[i]%mod;
jc[0]=jc[1]=1;
for(int i=1;i<N;i++)jc[i]=jc[i-1]*i%mod;
}
//初始化 ny记录逆元 jcny记录逆元的阶乘 jc记录阶乘
int c(int a,int b){
if(b>a)return 0;
return jc[a]*jcny[a-b]%mod*jcny[b]%mod;
}
//用a!/(a-b!*b!)计算组合数
int lucas(int a,int b){
if(!b)return 1;
return c(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
//
exgcd
int exgcd(int a,int b,int &x,int &y){
//这里注意引用 因为要修改值
if(!b){
//显而易见的当ax+0y=a时 x=1,y=0
x=1,y=0;
return a;
int ret=exgcd(b,a%b,y,x);
//exgcd的本质 ax+by=bx+(a%b)y
y-=(a/b)*x;
//exgcd的操作 x1=y2 y1=x2-(a/b)*x2
return ret;
}
}
exgcd求逆元
int inv(int a,int b){
int x,y;
int d=exgcd(a,m,x,y);
return (d==1?(x+m)%m:-1);
}
//exgcd求逆元和线性同余方程道理相同
费马小定理求逆元
int inv(int a,int p){
//根据 费马小定理 a^p与a在mod p意义下同余
//可转为 a^p-2与a^-1在mod p意义下同余
return ksm(a,p-2,p);
}
线性求逆元
for(int i=2;i<n;i++){
int[i]=inv[p%i]*(p-p*i);
}
CRT
int crt(int k,int *a,int *r){
int n=1,ans=0;
for(int i=1;i<=k;i++)n=n*r[i];
//计算所有模数的积
for(int i=1;i<=k;i++){
int m=n/r[i],b,y;//记 m=Sigma(模数)/该模数
exgcd(m,r[i],b,y);//求解b*m mod r[i]=1得到m的逆元
ans=(ans+a[i]*m*b)%n;//得到c[i]=m[i]*m[i]^-1,和a[i]相乘得到解
}
return (ans%n+n)%n;//取模~
}
exCRT
int excrt(int k,int *a,int *r){
int m=a[i],ans=a[i];
for(int i=2;i<=2;i++){
int c=
}
}
欧拉筛+处理欧拉函数
bool vis[N];
int p[N],phi[N],cnt=1;
void initphi(){
phi[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])p[cnt++]=i,phi[i]=i-1;
//如果i并未被访问过i肯定为素数,素数的欧拉函数值为i-1
for(int j=1,v;(v=i*p[j])<N;j++){
vis[v]=1;
if(i%p[j]==0){
//如果p[j]为i的因子,则统计欧拉函数,并停下
phi[i*p[j]]=phi[i]*p[j];
break;
}else phi[i*p[j]]=phi[i]*phi[p[j]];
}
}
}
Miller Rabin
//本模板超纲,但由于好用,建议死记硬背
bool Miller_Rabin(int n,int s){
if(n==2)return 1;//2为唯一的偶质数,特判
if(n<2||!(n&1))return 0;//其他偶数肯定是质数,1啥也不是
int x,y,u=n-1,t=0;
while((u&1)==0)t++,u>>1;
for(int i=0;i<s;i++){//s为测试次数
int a=rand()%(n-1)+1;
int x=ksm(a,u,n);
for(int j=0;j<t;j++){
int y=ksm(x,x,n);
if(y==1&&x!+1&&x!=n-1)return 0;
x=y;
}
}
if(x!=1)return 0;
}
欧拉函数 单个、
int euler(int n){
int ret=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
ret-=ret/i;
while(!(n%i))n/=i;
}
}
if(n>1)ret-=ret/n;
return ret;
//不用说什么,就是分解质因数
}
除法分块
for(int l=1,r;l<=n;l=r+1){
r=(n/(n/l));
cout<<n/l<<" "<<r-l+1<<endl;
}
高斯消元
int now=1;
for(int i=1;i<=n;i++){
//TODO: 复习高斯消元
}
扫描线
//最终 到达了数学部分最长的模板,扫描线+线段树
//TODO: 在线段树模板写好后复习扫描线
数据结构~
单调栈
void insert(int x){
while(!sta.empty()&&sta.top()<x)sta.pop();
//维护单调性 不断pop掉不符合单调性的
sta.push(x);
}
单调队列
deque<int>d;
for(int i=1;i<=n;i++){
cin>>a;
while(!d.empty()&&d.end()>a)d.pop_back();
//维护单调性 不断pop掉不符合单调性的
d.push_back(a);
}
01trie
int t[N*31][2],nv=1;
void build(int p,int d,int v){
bool flag=(v&(1<<d));
if(!t[p][flag])t[p][fkag]=++nv;
if(d)build(t[p][flag],d-1,v);
//递归逐位枚举
}
int query(int p,int d,int v){
//查询按位异或
if(d<0)return 0;
bool flag(v&(1<<d));
if(t[p][!flag])return (1<<d)+query(t[p][!flag],d-1,v);
//不同为1
if(t[p][!flag])return query(t[p][flag],d-1,v);
//相同为0
}
ST表
int logn=21;
void pre(){
Logn[1]=0;
Logn[2]=1;
for (int i=3;i<maxn;i++) {
Logn[i] = Logn[i / 2] + 1;
}
}
for(int j=1;j<=logn;j++){
for(int i=1;i+(i<<j)-1<=n;i++){
f[i][j]=max(f[i][j-1],f[i+(i<<(j-1))][j-1]);
}
}
树状数组
#define lower_bit(x) (x)&-(x)
void add(int a,int c){
for(int i=a;i<=n;i+=lower_bit(i))tree[i]+=c;
}
void add(int r){
int ret=0;
for(int i=r;i>=1;i-=lower_bit(i))ret+=tree[i];
}
线段树
本文作者:Wubaozi123awa
本文链接:https://www.cnblogs.com/baoziawa/p/18503374
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步