模板——多项式
取模下的运算(模数确定)
点击查看代码
void inc(int& x,int y){
x+=y;
if(x>=P) x-=P;
if(x<0) x+=P;
}
int sum(int x,int y){
x+=y;
if(x>=P) x-=P;
if(x<0) x+=P;
return x;
}
void mul(int& x,int y){
x=1ll*x*y%P;
}
int prd(int x,int y){
return 1ll*x*y%P;
}
inline int fpw(int a,int x){
int s=1;
for(;x;x>>=1,a=prd(a,a)) if(x&1) s=prd(s,a);
return s;
}
组合数预处理
点击查看代码
const int N=4e5+5;
int P;
inline int fpw(int a,int x){
int s=1;
for(;x;x>>=1,a=1ll*a*a%P) if(x&1) s=1ll*s*a%P;
return s;
}
int rv[N],iv[N],fc[N],fv[N],pw[N];
void init(int n){
fc[0]=pw[0]=1;
for(int i=1;i<n;i++) iv[i]=fpw(i,P-2),fc[i]=1ll*fc[i-1]*i%P,pw[i]=1ll*pw[i-1]*2%P;
fv[n-1]=fpw(fc[n-1],P-2);
for(int i=n-2;~i;i--) fv[i]=1ll*fv[i+1]*(i+1)%P;
}
int C(int n,int m){
if(m<0 || m>n) return 0;
return 1ll*fc[n]*fv[m]%P*fv[n-m]%P;
}
多项式乘法+求逆+开根+Ln+Exp
(因为一些奇特的原因,预处理得开到四倍)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=(1<<20)+5,P=998244353,G[2]={3,(P+1)/3};
inline int fpw(int a,int x){
int s=1;
for(;x;x>>=1,a=1ll*a*a%P) if(x&1) s=1ll*s*a%P;
return s;
}
int rv[N],gp[2][N],iv[N],fc[N],fv[N];
void init(int n){
fc[0]=1;
for(int i=1;i<n;i++) iv[i]=fpw(i,P-2),fc[i]=1ll*fc[i-1]*i%P;
fv[n-1]=fpw(fc[n-1],P-2);
for(int i=n-2;~i;i--) fv[i]=1ll*fv[i+1]*(i+1)%P;
for(int p=0;p<2;p++){
for(int i=1;i<n;i<<=1){
gp[p][i]=1;
int t=fpw(G[p],(P-1)/(i<<1));
for(int j=i+1;j<(i<<1);j++) gp[p][j]=1ll*gp[p][j-1]*t%P;
}
}
}
//cnt:f[0]-f[n-1]
void print(char name[],int n,int* a){
printf("%s n=%d\n",name,n);
for(int i=0;i<n;i++) cout<<a[i]<<" "; puts("");
}
inline void dft(int* a,int n,int p){
for(int i=0;i<n;i++) if(i<rv[i]) swap(a[i],a[rv[i]]);
for(int i=1;i<n;i<<=1){
for(int j=0;j<n;j+=(i<<1)){
for(int k=0;k<i;k++){
int &A=a[i+j+k],&B=a[j+k],t=1ll*gp[p][i+k]*A%P;
A=B-t; if(A<0) A+=P;
B=B+t; if(B>=P) B-=P;
}
}
}
if(p) for(int i=0;i<n;i++) a[i]=1ll*a[i]*iv[n]%P;
}
inline int Rev(int m){
int p=0,n=1;
while(n<m) n<<=1,p++;
for(int i=0;i<n;i++) rv[i]=(rv[i>>1]>>1)|((i&1)<<(p-1));
return n;
}
inline void poly_mul(int m,int* A,int* B,int* C){
int n=Rev(m);
dft(A,n,0); dft(B,n,0);
for(int i=0;i<n;i++) C[i]=1ll*A[i]*B[i]%P;
dft(C,n,1);
fill(C+m,C+n,0);
}
//C=A*B m:需要C的0~(m-1)项,m~(n-1)为空
int C[N],D[N];
inline void poly_inv(int m,int *a, int *b) {
if(m==1){
b[0]=fpw(a[0],P-2);
return;
}
poly_inv((m + 1)>>1,a,b);
int n=Rev(m<<1);
copy(a,a+m,C);
fill(C+m,C+n,0);
dft(b,n,0); dft(C,n,0);
for(int i=0;i<n;i++) b[i]=1ll*b[i]*(P+2-1ll*b[i]*C[i]%P)%P;
dft(b,n,1);
fill(b+m,b+n,0);
}
//a*b=1,给定a的0~(m-1)项,返回b的0~(m-1)项
//需要保证初始b为空!
inline void poly_sqrt(int m,int* a,int* b){
if(m==1){
b[0]=1;
return;
}
poly_sqrt((m+1)>>1,a,b);
poly_inv(m,b,D);
int n=Rev(m<<1);
copy(a,a+m,C);
fill(C+m,C+n,0);
dft(C,n,0); dft(D,n,0);
for(int i=0;i<n;i++) C[i]=1ll*D[i]%P*C[i]%P;
dft(C,n,1);
for(int i=0;i<n;i++) b[i]=1ll*(P+1)/2*(b[i]+C[i])%P;
fill(b+m,b+n,0);
fill(D,D+n,0);
}
//b*b=a,给定a的0~(m-1)项,返回b的0~(m-1)项
//需要保证初始b为空!
inline void poly_Ln(int m,int* a,int* b){
poly_inv(m,a,b);
for(int i=0;i<m-1;i++) C[i]=1ll*a[i+1]*(i+1)%P; C[m-1]=0;
int n=Rev(m<<1);
fill(C+m,C+n,0);
dft(C,n,0); dft(b,n,0);
for(int i=0;i<n;i++) b[i]=1ll*C[i]*b[i]%P;
dft(b,n,1);
for(int i=m-1;i;i--) b[i]=1ll*b[i-1]*iv[i]%P; b[0]=0;
fill(b+m,b+n,0);
}
//b=Ln(a),给定a的0~(m-1)项,返回b的0~(m-1)项
//需要保证初始b为空!
inline void poly_Exp(int m,int* a,int* b){
if(m==1){
b[0]=1;
return;
}
poly_Exp((m+1)>>1,a,b);
poly_Ln(m,b,D);
for(int i=0;i<m;i++) D[i]=(P+a[i]-D[i]+(i==0))%P;
int n=Rev(m<<1);
dft(b,n,0); dft(D,n,0);
for(int i=0;i<n;i++) b[i]=1ll*b[i]*D[i]%P;
dft(b,n,1);
fill(b+m,b+n,0);
fill(D,D+n,0);
}
//b=Exp(a),给定a的0~(m-1)项,返回b的0~(m-1)项
//需要保证初始b为空!
int main(){
return 0;
}
FWT
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void fwt(ll* a,int n,int op){
for(int i=1;i<n;i<<=1)
for(int p=(i<<1),j=0;j<n;j+=p)
for(int k=0;k<i;++k){
ll x=a[j+k],y=a[i+j+k];
a[j+k]=x+y; a[i+j+k]=x-y;
if(op==-1) a[j+k]/=2,a[i+j+k]/=2;
}
}
const int N=(1<<20);
int n,m,a[N];
ll k,A[N];
char ch[N];
int main()
{
//srand(time(0));
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
//int T; cin>>T; while(T--) work();
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
scanf("%s",ch);
for(int j=0;j<m;j++) a[i]+=(1<<j)*(ch[j]-'A');
A[a[i]]++;
}
fwt(A,(1<<m),1);
for(int i=0;i<(1<<m);i++) A[i]*=A[i];
fwt(A,(1<<m),-1);
A[0]-=n; //cout<<A[0]<<endl;
for(int i=0;i<(1<<m);i++) A[i]>>=1;//cout<<A[i]<<" "; puts("");
for(int i=1;i<=m;i++){
for(int s=0;s<(1<<(m-i));s++){
for(int t=0;t<(1<<(i-1));t++)
A[(s<<i)+(1<<(i-1))+t]+=A[(s<<i)+t];
}
}
int s=0;
for(int i=0;i<(1<<m);i++) if(A[i]<=(1ll*n*(n-1)/2-k)) s++;
cout<<s<<endl;
return 0;
分类:
XCPC——计数(组合,多项式)
标签:
模板
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探