1. 程式人生 > 其它 >省選模擬24

省選模擬24

排隊 暱稱 帝國防衛

A. 排隊

\(f_{i,j}\) 表示前 \(i\) 個人有 \(j\) 個刺頭的方案數

那麼轉移長這樣 \(f_{i,j}=f_{i-1,j}*2*j+f_{i-1,j-1}*(i-2*(j-1))\)

第一種是直接放在原來的刺頭旁邊把他替換掉

第二種是放在其他地方成為一個新刺頭

發現模數以及 \(m\) 都很小

於是可以處理一下前模數個的轉移,整個陣列表示哪個位置對哪個位置的貢獻係數

然後再倍增處理一下相同的,最後剩下的暴力轉移

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,mod;
int a[1010][12][12];
int base[12][12],res[12],tmp[12][12];
inline void qpow(int k){
	for(int i=0;i<=m;i++) for(int j=0;j<=m;j++) base[i][j]=a[mod][i][j];res[0]=1;
	while(k){
		if(k&1){
			for(int i=0;i<=m;i++) tmp[0][i]=res[i];
			for(int i=0;i<=m;i++) res[i]=0;
			for(int i=0;i<=m;i++) for(int j=0;j<=m;j++) (res[j]+=tmp[0][i]*base[i][j])%=mod;
		}
		for(int i=0;i<=m;i++) for(int j=0;j<=m;j++) tmp[i][j]=base[i][j];
		for(int i=0;i<=m;i++) for(int j=0;j<=m;j++) base[i][j]=0;
		for(int i=0;i<=m;i++) for(int K=i;K<=m;K++) for(int j=K;j<=m;j++) (base[i][j]+=tmp[i][K]*tmp[K][j])%=mod;
		k>>=1;
	}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("queue.in","r",stdin);
	freopen("queue.out","w",stdout);
	n=read(),m=read(),mod=read();
	for(int i=0;i<=m;i++) a[0][i][i]=1;
	for(int k=1;k<=mod;k++){
		for(int i=0;i<=m;i++) for(int j=0;j<=m;j++){
			a[k][i][j]+=a[k-1][i][j]*2*j;
			a[k][i][j+1]+=a[k-1][i][j]*(k-2*j);
		}
		for(int i=0;i<=m;i++) for(int j=0;j<=m;j++) a[k][i][j]%=mod;
	}
	qpow(n/mod);
	int lim=n%mod;
	for(int i=0;i<=m;i++) tmp[0][i]=res[i];
	for(int i=0;i<=m;i++) res[i]=0;
	for(int i=0;i<=m;i++) for(int j=0;j<=m;j++) (res[j]+=tmp[0][i]*a[lim][i][j])%=mod;
	printf("%lld\n",res[m]);
	return 0;
}

B. 暱稱

數位 \(dp\)\(f_{x,y,0/1,0/1}\) 表示考慮到第 \(x\) 位,前面匹配到了 \(kmp\) 上的 \(y\) 這個位置,然後是否包含完整的串,是否有前導零的方案數

然後用方案數求方案就行

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define rint signed
#define meow(args...) fprintf(stderr,args)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,N;
int kmp[1010],ans[1030];
map<bool,int>f[1030][1010][2];
char st[1010];
int dfs(int x,int y,bool v1,bool v2){
	if(f[x][y][v1].find(v2)!=f[x][y][v1].end()) return f[x][y][v1][v2];
	if(!x) return f[x][y][v1][v2]=v1;
	int res=0,tmp;
	for(int i=0,ty,tv1,tv2;i<=9;i++){
		ty=y;tv2=v2|(i!=0);
		if(tv2){
			while(ty&&st[ty+1]!=(i+'0')) ty=kmp[ty];
			if(st[ty+1]==(i+'0')) ty++;
		}
		tv1=v1|(ty==n);
		tmp=dfs(x-1,ty,tv1,tv2);if(tv2) res+=tmp;
	}
	return f[x][y][v1][v2]=res;
}
void print(int x,int y,bool v1,bool v2,int K){
	if(!x) return ;
	for(int i=v2,ty,tv1;i<=9;i++){
		ty=y;
		while(ty&&st[ty+1]!=(i+'0')) ty=kmp[ty];
		if(st[ty+1]==(i+'0')) ty++;
		tv1=v1|(ty==n);
		if(K<=f[x-1][ty][tv1][1]){
			ans[x]=i;print(x-1,ty,tv1,0,K);
			break;
		}else K-=f[x-1][ty][tv1][1];
	}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("nickname.in","r",stdin);
	freopen("nickname.out","w",stdout);
	scanf("%s",st+1);n=strlen(st+1);N=read();
	for(int i=2,j=0;i<=n;i++){
		while(j&&st[j+1]!=st[i]) j=kmp[j];
		if(st[i]==st[j+1]) j++;
		kmp[i]=j;
	}
	dfs(n+17,0,0,0);
	for(int i=n;;i++){
		if(N<=f[i][0][0][0]){
			print(i,0,0,1,N);
			for(int j=i;j;j--) putchar(ans[j]+'0');
			break;
		}else N-=f[i][0][0][0];
	}
	return 0;
}

C. 帝國防衛

對每個深度開一個線段樹用來維護還差多少能比 \(c_x\)

\(dfs\) 序暴力跳父親再暴力列舉深度修改區間,順便維護最小值

如果最小值小於等於 \(0\) 了,就遞迴下去,直到單點,再用個樹狀陣列去維護個數

複雜度 \(O(n\log^3 n)\)

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define lson st[x].ls
#define rson st[x].rs
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,mxd;
int rt[100010],cnt;
int c[100010],a[100010],b[100010];
int head[100010],ver[200010],to[200010],tot;
int fa[100010],dfn[100010],siz[100010],dep[100010],clo;
inline void add(int x,int y){ver[++tot]=y;to[tot]=head[x];head[x]=tot;}
int BIT[100010];
struct seg{int mn,atag,ls,rs;}st[100010*20];
inline void ins(int x){for(;x<=n;x+=x&-x) BIT[x]++;}
inline int query(int x){if(!x) return 0;int res=0;for(;x;x-=x&-x) res+=BIT[x];return res;}
inline int ask(int l,int r){return query(r)-query(l-1);}
inline void pushup(int x){
	st[x].mn=inf;
	if(lson) st[x].mn=min(st[lson].mn,st[x].mn);
	if(rson) st[x].mn=min(st[rson].mn,st[x].mn);
}
inline void pushdown(int x){
	if(st[x].atag){
		if(lson) st[lson].atag+=st[x].atag,st[lson].mn+=st[x].atag;
		if(rson) st[rson].atag+=st[x].atag,st[rson].mn+=st[x].atag;
		st[x].atag=0;
	}
}
void ins(int &x,int l,int r,int pos,int k){
	if(!x) x=++cnt;if(l==r) return st[x].mn=k,void();
	int mid=(l+r)>>1;
	if(pos<=mid) ins(lson,l,mid,pos,k);
	else ins(rson,mid+1,r,pos,k);
	pushup(x);
}
void upd(int x,int l,int r,int L,int R,int k){
	if(!x) return ;
	if(L<=l&&r<=R) return st[x].mn+=k,st[x].atag+=k,void();
	int mid=(l+r)>>1;pushdown(x);
	if(L<=mid) upd(lson,l,mid,L,R,k);
	if(R>mid) upd(rson,mid+1,r,L,R,k);
	pushup(x);
}
void chg(int x,int l,int r){
	if(l==r) return st[x].mn=inf,ins(l),void();
	int mid=(l+r)>>1;pushdown(x);
	if(lson&&st[lson].mn<=0) chg(lson,l,mid);
	if(rson&&st[rson].mn<=0) chg(rson,mid+1,r);
	pushup(x);
}
void dfs(int x,int fa){
	dfn[x]=++clo,siz[x]=1;dep[x]=dep[fa]+1;::fa[x]=fa;mxd=max(mxd,dep[x]);
	for(int i=head[x];i;i=to[i]){
		int y=ver[i];if(y==fa) continue;
		dfs(y,x);siz[x]+=siz[y];
	}
}
void down(int x,int k,int L,int R){
	if(!k||!x) return ;int now=k,depx=dep[x];
	while(now&&depx<=mxd){
		if(!L){
			upd(rt[depx],1,n,dfn[x],dfn[x]+siz[x]-1,-now);
		}else{
			if(dfn[x]<=L-1) upd(rt[depx],1,n,dfn[x],L-1,-now);
			if(R+1<=dfn[x]+siz[x]-1) upd(rt[depx],1,n,R+1,dfn[x]+siz[x]-1,-now);
		}
		now/=2,depx++;
	}
	down(fa[x],k/2,dfn[x],dfn[x]+siz[x]-1);
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("empire.in","r",stdin);
	freopen("empire.out","w",stdout);
	n=read();for(int i=1;i<=n;i++) c[i]=read();
	for(int i=1,x,y;i<n;i++){x=read(),y=read();add(x,y),add(y,x);}
	dfs(1,0);
	for(int i=1;i<=n;i++) ins(rt[dep[i]],1,n,dfn[i],c[i]);
	m=read();
	for(int i=1,op,x,k;i<=m;i++){
		op=read(),x=read();
		if(op==1){
			k=read();down(x,k,0,0);
			for(int i=0;i<=20;i++) if(dep[x]+i<=mxd) chg(rt[dep[x]+i],1,n);
			for(int i=0;i<=20;i++) if(dep[x]-i>=1) chg(rt[dep[x]-i],1,n);
		}else printf("%lld\n",ask(dfn[x],dfn[x]+siz[x]-1));
	}
	return 0;
}