190831 CSP-S 2019 模拟

本文介绍了CSP-S 2019模拟考试中的三道题目,包括A题的线段树解决方案,B题通过lct维护等比数列和的技巧,以及C题的容斥原理与整数拆分解法。在解题过程中,作者分享了遇到的难点和解决思路,提醒读者注意避免在考试中出现类似错误。
摘要由CSDN通过智能技术生成

A

辣鸡 s t d std std 不知道你想表达些啥非要多写个没用的函数还把复杂度上界算错了
这题做法trival,写起来去世

考虑到没有最后一个询问就是常规吉司机线段树,现在我们构造一个 C i = A i − B i C_i=A_i-B_i Ci=AiBi

这样最后就问的是 s u m A − s u m C sum_A-sum_C sumAsumC

我们发现只用在改 A A A 的时候顺便改一下 C C C 然后把 C C C 中的元素每次修改之后跟 0   c k m a x 0\ ckmax 0 ckmax 一下,这操作不就是 A A A 的操作吗???

于是封装一下就写好了(代码调一年

注意我们要把 C C C 这个集合里的最小值和非最小值分开维护

代码:

#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
#define pb push_back
#define rsz resize
#define sz(x) (int)(x).size()
#define lb lower_bound
#define rb upper_bound
#define all(x) begin(x),end(x)
using namespace std;
using namespace __gnu_pbds;
template<class T>using Tree=tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
const int mod=998244353;
typedef long long ll;
inline ll readl(){
	ll ans=0;
	char ch=gc();
	bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
const int mogic=1e6+7;
struct Hash_table{
	vector<int>ori[mogic],vl[mogic];
	inline void insert(int x,int Vl){
		int t=x<mogic?x:x-x/mogic*mogic;
		ori[t].pb(x),vl[t].pb(Vl);
	}
	inline int query(int x){
		for(ri t=x<mogic?x:x-x/mogic*mogic,i=sz(ori[t])-1;~i;--i)if(ori[t][i]==x)return vl[t][i];
		return -1;
	}
};
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N_=1e6+5;
vector<int>e[N_];
inline void rdt1(int n){for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdt2(int n){for(ri i=2;i<=n;++i)e[read()].pb(i);}
inline void rdg1(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdg2(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v);}
const int N=1e5+5,inf=1e9;
struct Min{
	int mn,ct,sn,siz;
	ll ss;
	inline void clear(){sn=(mn=inf)+1,ss=siz=ct=0;}
	inline void Set(int vl){
		if(vl==inf)return clear();
		sn=inf,ss=mn=vl,ct=siz=1;
	}
};
struct Tag{int ad1,ad2;inline void clear(){ad1=ad2=0;}};
struct F{
	Min vl;
	Tag tg;
	inline void clear(){vl.clear(),tg.clear();}
	inline void Set(int v){tg.clear(),vl.Set(v);}
};
inline Min operator+(Min a,Tag b){return a.mn+=b.ad1,a.sn+=b.ad2,a.ss+=(ll)a.ct*b.ad1+(ll)(a.siz-a.ct)*b.ad2,a;}
inline void operator+=(Min&a,Tag b){a=a+b;}
inline Tag operator+(Tag a,Tag b){return a.ad1+=b.ad1,a.ad2+=b.ad2,a;}
inline void operator+=(Tag&a,Tag b){a=a+b;}
inline F operator+(F a,Tag b){return b.ad2*=(a.vl.sn<inf),a.vl+=b,a.tg+=b,a;}
inline void operator+=(F&a,Tag b){a=a+b;}
inline void ckmin(int&a,int b){a=a<b?a:b;}
inline Min operator+(Min a,Min b){
	if(a.mn>b.mn)swap(a,b);
	if(a.mn==b.mn)a.ct+=b.ct,ckmin(a.sn,b.sn);
	else ckmin(a.sn,b.mn);
	return a.siz+=b.siz,a.ss+=b.ss,a;
}
inline void operator+=(Min&a,Min b){a=a+b;}
inline void operator+=(F&a,F b){if(b.vl.mn!=a.vl.mn+b.tg.ad1)b.tg.ad1=b.tg.ad2;a+=b.tg;}
struct Node{F ori,mn,sn;};
int a[N],n,m;
namespace sgt{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	Node T[N<<2];
	inline void pushdown(int p){
		T[lc].ori+=T[p].ori;
		T[rc].ori+=T[p].ori;
		T[lc].mn+=(T[p].ori.vl.mn==T[lc].ori.vl.mn?T[p].mn:T[p].sn);
		T[rc].mn+=(T[p].ori.vl.mn==T[rc].ori.vl.mn?T[p].mn:T[p].sn);
		T[lc].sn+=T[p].sn;
		T[rc].sn+=T[p].sn;
		T[p].ori.tg.clear(),T[p].mn.tg.clear(),T[p].sn.tg.clear();
	}
	inline void pushup(int p){
		T[p].ori.vl=T[lc].ori.vl+T[rc].ori.vl;
		T[p].sn.vl=T[lc].sn.vl+T[rc].sn.vl;
		T[p].mn.vl.clear();
		(T[p].ori.vl.mn==T[lc].ori.vl.mn?T[p].mn.vl:T[p].sn.vl)+=T[lc].mn.vl;
		(T[p].ori.vl.mn==T[rc].ori.vl.mn?T[p].mn.vl:T[p].sn.vl)+=T[rc].mn.vl;
	}
	inline void build(int p,int l,int r){
		if(l==r)return T[p].ori.Set(a[l]),T[p].mn.Set(0),T[p].sn.Set(inf);
		build(lc,l,mid),build(rc,mid+1,r);
		pushup(p);
	}
	inline void update_ori(int p,int l,int r,int v){
		if(T[p].ori.vl.mn>=v)return;
		if(T[p].ori.vl.sn>v){
			Tag tg;
			tg.ad1=v-T[p].ori.vl.mn,tg.ad2=0,T[p].ori+=tg,
			tg.ad2=tg.ad1,T[p].mn+=tg;
			return;
		}
		pushdown(p);
		update_ori(lc,l,mid,v),update_ori(rc,mid+1,r,v);
		pushup(p);
	}
	inline void update_max(int p,int l,int r,int ql,int qr,int v){
		if(ql<=l&&r<=qr)return update_ori(p,l,r,v);
		pushdown(p);
		if(qr<=mid)update_max(lc,l,mid,ql,qr,v);
		else if(ql>mid)update_max(rc,mid+1,r,ql,qr,v);
		else update_max(lc,l,mid,ql,qr,v),update_max(rc,mid+1,r,ql,qr,v);
		pushup(p);
	}
	inline void update(int p,int l,int r,int v,bool f1,bool f2){
		if(f1){
			Tag tg;
			tg.ad2=v;
			if(T[p].mn.vl.mn+v>=0)f1=0,tg.ad1=v,T[p].mn+=tg;
			else if(T[p].mn.vl.sn+v>=0)f1=0,tg.ad1=-T[p].mn.vl.mn,T[p].mn+=tg;
		}
		if(f2){
			Tag tg;
			tg.ad2=v;
			if(T[p].sn.vl.mn+v>=0)f2=0,tg.ad1=v,T[p].sn+=tg;
			else if(T[p].sn.vl.sn+v>=0)f2=0,tg.ad1=-T[p].sn.vl.mn,T[p].sn+=tg;
		}
		if(!(f1|f2))return;
		pushdown(p);
		update(lc,l,mid,v,T[lc].ori.vl.mn==T[p].ori.vl.mn?f1:f2,f2);
		update(rc,mid+1,r,v,T[rc].ori.vl.mn==T[p].ori.vl.mn?f1:f2,f2);
		pushup(p);
	}
	inline void update_add(int p,int l,int r,int ql,int qr,int v){
		if(ql<=l&&r<=qr){
			Tag tg;
			tg.ad1=tg.ad2=v;
			T[p].ori+=tg;
			return update(p,l,r,v,1,1);
		}
		pushdown(p);
		if(qr<=mid)update_add(lc,l,mid,ql,qr,v);
		else if(ql>mid)update_add(rc,mid+1,r,ql,qr,v);
		else update_add(lc,l,mid,ql,qr,v),update_add(rc,mid+1,r,ql,qr,v);
		pushup(p);
	}
	inline ll q1(int p,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return T[p].ori.vl.ss;
		pushdown(p);
		if(qr<=mid)return q1(lc,l,mid,ql,qr);
		if(ql>mid)return q1(rc,mid+1,r,ql,qr);
		return q1(lc,l,mid,ql,qr)+q1(rc,mid+1,r,ql,qr);
	}
	inline ll q2(int p,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return T[p].ori.vl.ss-T[p].mn.vl.ss-T[p].sn.vl.ss;
		pushdown(p);
		if(qr<=mid)return q2(lc,l,mid,ql,qr);
		if(ql>mid)return q2(rc,mid+1,r,ql,qr);
		return q2(lc,l,mid,ql,qr)+q2(rc,mid+1,r,ql,qr);
	}
	#undef lc
	#undef rc
	#undef mid
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	n=read(),m=read();
	for(ri i=1;i<=n;++i)a[i]=read();
	sgt::build(1,1,n);
	for(ri op,l,r;m;--m){
		op=read(),l=read(),r=read();
		if(op==1)sgt::update_max(1,1,n,l,r,read());
		if(op==2)sgt::update_add(1,1,n,l,r,read());
		if(op==3)cout<<sgt::q1(1,1,n,l,r)<<'\n';
		if(op==4)cout<<sgt::q2(1,1,n,l,r)<<'\n';
	}
	return 0;
}

B

一道比较 n a i i v e naiive naiive 的题,发现只需要用 l c t lct lct 维护一坨等比数列的和,但 5 5 5 没有二次剩余于是要写个矩阵或者 a + b 5 a+b\sqrt5 a+b5 来搞一下,代码也挺简单的:

#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
#define pb push_back
#define rsz resize
#define sz(x) (int)(x).size()
#define lb lower_bound
#define rb upper_bound
#define all(x) begin(x),end(x)
using namespace std;
using namespace __gnu_pbds;
template<class T>using Tree=tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
const int mod=998244353;
typedef long long ll;
inline ll readl(){
	ll ans=0;
	char ch=gc();
	bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
const int mogic=1e6+7;
struct Hash_table{
	vector<int>ori[mogic],vl[mogic];
	inline void insert(int x,int Vl){
		int t=x<mogic?x:x-x/mogic*mogic;
		ori[t].pb(x),vl[t].pb(Vl);
	}
	inline int query(int x){
		for(ri t=x<mogic?x:x-x/mogic*mogic,i=sz(ori[t])-1;~i;--i)if(ori[t][i]==x)return vl[t][i];
		return -1;
	}
};
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N_=1e6+5;
vector<int>e[N_];
inline void rdt1(int n){for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdt2(int n){for(ri i=2;i<=n;++i)e[read()].pb(i);}
inline void rdg1(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdg2(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v);}
const int N=1e5+5;
int n,m,a[N];
Hash_table S;
struct F{
	int x,y;
	F(int x=0,int y=0):x(x),y(y){}
	inline F conj()const{return F(x,mod-y);}
	friend inline F operator+(F a,F b){return F(add(a.x,b.x),add(a.y,b.y));}
	friend inline F operator-(F a,F b){return F(dec(a.x,b.x),dec(a.y,b.y));}
	friend inline F operator*(F a,F b){return F(add(mul(a.x,b.x),mul(5,mul(a.y,b.y))),add(mul(a.x,b.y),mul(a.y,b.x)));}
	friend inline F operator*(F a,int b){return F(mul(a.x,b),mul(a.y,b));}
	friend inline F operator/(F a,F b){
		int t=dec(mul(b.x,b.x),mul(5,mul(b.y,b.y))),iv=S.query(t);
		if(iv==-1){
			iv=t?ksm(t,mod-2):1;
			S.insert(t,iv);
		}
		return (a*(b.conj()))*iv;
	}
	friend inline void operator+=(F&a,F b){a=a+b;}
	friend inline void operator-=(F&a,F b){a=a-b;}
	friend inline void operator*=(F&a,F b){a=a*b;}
	friend inline void operator/=(F&a,F b){a=a/b;}
	friend inline F operator^(F a,int p){F ret=F(1,0);for(;p;p>>=1,a*=a)if(p&1)ret*=a;return ret;}
};
const F W0=F(mod+1>>1,mod+1>>1);
struct G{
	F pre,suf,ss,vl;
	G(F pre=F(0,0),F suf=F(0,0),F ss=F(0,0),F vl=F(0,0)):pre(pre),suf(suf),ss(ss),vl(vl){}
	inline void rev(){swap(pre,suf);}
	friend inline G operator+(G a,G b){return G(a.pre+a.vl*b.pre,b.suf+b.vl*a.suf,a.ss+b.ss+a.suf*b.pre,a.vl*b.vl);}
};
inline G Set(F v=F(0,0),int k=1){
	G t;
	F iv=F(1,0)/(F(1,0)-v);
	t.vl=v^k;
	t.pre=t.suf=(F(1,0)-t.vl)*v*iv;
	t.ss=(F(k,0)-t.pre)*iv*v;
	return t;
}
namespace lct{
	#define lc (son[p][0])
	#define rc (son[p][1])
	int son[N][2],siz[N],fa[N];
	F tg[N],vl[N];
	bool rev[N],cov[N];
	G T[N];
	inline void pushup(int p){
		T[p]=Set(vl[p],1),siz[p]=1;
		if(lc)T[p]=T[lc]+T[p],siz[p]=siz[lc]+siz[p];
		if(rc)T[p]=T[p]+T[rc],siz[p]=siz[p]+siz[rc];
	}
	inline void pushrev(int p){swap(lc,rc),T[p].rev(),rev[p]^=1;}
	inline void pushcov(int p,F v){cov[p]=1,T[p]=Set(tg[p]=vl[p]=v,siz[p]);}
	inline void pushdown(int p){
		if(rev[p]){
			rev[p]^=1;
			if(lc)pushrev(lc);
			if(rc)pushrev(rc);
		}
		if(cov[p]){
			cov[p]^=1;
			if(lc)pushcov(lc,tg[p]);
			if(rc)pushcov(rc,tg[p]);
		}
	}
	inline bool which(int x){return x==son[fa[x]][1];}
	inline bool isroot(int x){return !fa[x]||(son[fa[x]][0]!=x&&son[fa[x]][1]!=x);}
	inline void rotate(int x){
		int y=fa[x],z=fa[y],t=which(x);
		if(z&&!isroot(y))son[z][which(y)]=x;
		fa[x]=z,fa[y]=x,son[y][t]=son[x][t^1],son[x][t^1]=y;
		if(son[y][t])fa[son[y][t]]=y;
		pushup(y),pushup(x);
	}
	inline void splay(int x){
		static int stk[N],top=0;
		stk[top=1]=x;
		for(ri i=x;!isroot(i);i=fa[i])stk[++top]=fa[i];
		while(top)pushdown(stk[top--]);
		while(!isroot(x)){
			if(!isroot(fa[x]))rotate(which(x)^which(fa[x])?x:fa[x]);
			rotate(x);
		}
	}
	inline void access(int x){for(ri y=0;x;x=fa[y=x])splay(x),son[x][1]=y,(y)&&(fa[y]=x),pushup(x);}
	inline void makeroot(int x){access(x),splay(x),pushrev(x);}
	inline void link(int x,int y){makeroot(x),splay(y),fa[x]=y;}
	inline void cut(int x,int y){makeroot(x),access(y),splay(y),son[y][0]=fa[x]=0,pushup(y);}
	inline void update1(int x,int y){
		makeroot(1),access(x),splay(x);
		fa[son[x][0]]=0,son[x][0]=0,pushup(x),fa[x]=y;
	}
	inline void update2(int x,int y,int v){
		makeroot(x),access(y),splay(y);
		pushcov(y,W0^v);
	}
	inline int query1(int x){return splay(x),add(vl[x].y,vl[x].y);}
	inline int query2(int x,int y){return makeroot(x),access(y),splay(y),add(T[y].ss.y,T[y].ss.y);}
	inline void init(int p,int k){T[p]=Set(vl[p]=W0^k,siz[p]=1);}
	#undef lc
	#undef rc
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	n=read(),m=read();
	for(ri i=1;i<=n;++i)lct::init(i,read());
	for(ri i=2;i<=n;++i)lct::fa[i]=read();
	for(ri op,x,y;m;--m){
		op=read();
		if(op==1){
			x=read(),y=read();
			lct::update1(x,y);
		}
		if(op==2){
			x=read(),y=read();
			lct::update2(x,y,read());
		}
		if(op==3)cout<<lct::query1(read())<<'\n';
		if(op==4){
			x=read(),y=read();
			cout<<lct::query2(x,y)<<'\n';
		}
	}
	return 0;
}

C

我考试的时候怎么给自己套了个 n \sqrt n n 进去呀???(自闭.jpg

而且讲过的原题一坨人没去写???

直接先推一个容斥系数然后枚举整数拆分加个分解质因数再做完全背包就完了。

代码(多套了一个 n \sqrt n n 的):

#include<bits/stdc++.h>
#define ri register int
#define rs register short
#define fi first
#define se second
#define lb lower_bound
#define ub upper_bound
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define rsz resize
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
const int mod=1e9+7;
typedef long long ll;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e4+5,M=31;
short top=0,a[N],b[N],pri[N],tot=0,n,m;
int g[M],fac[M],ifac[M],ans=0,cnt[N];
int mt_fac[M][M],mt_ifac[M][M],mt_g[M][M];
bool vis[N];
int ff[N];
inline void calc(){
	int coe=1;
	for(rs i=1;i<=top;++i){
		coe=(1ll*coe*mt_ifac[a[i]][b[i]])%mod*(1ll*ifac[b[i]]*mt_g[a[i]][b[i]]%mod)%mod;
		if(!coe)return;
	}
	for(rs i=1;i<=tot;++i){
		ff[0]=1;
		for(ri j=1;j<=cnt[i];++j)ff[j]=0;
		for(rs j=1;j<=top;++j)for(rs k=1;k<=b[j];++k)
		for(ri t=0,up=cnt[i]-a[j];t<=up;++t)Add(ff[t+a[j]],ff[t]);
		Mul(coe,ff[cnt[i]]);
		if(!coe)return;
	}
	Add(ans,coe);
}
void dfs(short x,short y){
	if(x<y)return;
	if(a[top]==x){
		++b[top];
		calc();
		--b[top];
	}
	else{
		a[++top]=x,b[top]=1;
		calc();
		--top;
	}
	for(rs i=y,lim=x/2;i<=lim;++i){
		if(i==a[top]){
			++b[top];
			dfs(x-i,i);
			--b[top];
		}
		else{
			a[++top]=i,b[top]=1;
			dfs(x-i,i);
			--top;
		}
	}
}
inline void Init(int x){for(ri i=n;i>=x;i/=x)cnt[tot]+=i/x;}
inline void init(){
	for(rs i=2;i<=n;++i){
		if(!vis[i])pri[++tot]=i,Init(i);
		for(rs j=1;j<=tot&&(int)i*pri[j]<=n;++j){
			vis[i*pri[j]]=1;
			if(i==i/pri[j]*pri[j])break;
		}
	}
	fac[0]=ifac[0]=fac[1]=ifac[1]=1;
	for(rs i=2;i<=m;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(rs i=2;i<=m;++i)Mul(ifac[i],ifac[i-1]);
	g[1]=1;
	for(rs i=2;i<=m;++i)g[i]=mod-mul(g[i-1],i-1);
	for(rs i=1;i<=m;++i)mt_fac[i][0]=mt_ifac[i][0]=mt_g[i][0]=1;
	for(rs i=1;i<=m;++i)for(rs j=1;j<=m;++j)mt_fac[i][j]=mul(mt_fac[i][j-1],fac[i]);
	for(rs i=1;i<=m;++i)for(rs j=1;j<=m;++j)mt_ifac[i][j]=mul(mt_ifac[i][j-1],ifac[i]);
	for(rs i=1;i<=m;++i)for(rs j=1;j<=m;++j)mt_g[i][j]=mul(mt_g[i][j-1],g[i]);
}
int main(){
	n=read(),m=read();
	init();
	dfs(m,1);
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值