省選模擬24
阿新 • • 發佈:2022-03-03
排隊 暱稱 帝國防衛
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; }