[atAGC055F]Creative Splitting
作者:互联网
考虑判定序列$\{b_{i}\}$是否"amazing",从后往前拆分,即等价于如下问题:
初始$c_{i}$均为$k$(长度为$n$),从大到小枚举$i$并选择$c_{j}\ge b_{i}$减1,判定最终能否使$c_{i}$均为0
关于这个问题,可以贪心选择最小的$c_{j}$操作,证明如下:
注意到$c_{i}$是无序的,即$c_{x}=c_{y}$时操作$x$和$y$是等价的
引理:对于任意有解的$c_{i}$,贪心操作一次后仍有解
假设贪心操作$x$而某组解操作$y$,若$c_{x}=c_{y}$即得证,否则也即有$c_{x}<c_{y}$
为了方便,强制该组解在$c_{x}=c_{y}$时不操作$y$(操作$x$等价),即恒有$c_{x}\le c_{y}$
构造:操作$x$后模仿该组解操作,仅将下一次操作$x$改为操作$y$
考虑构造的合法性,分为三部分:
1.下一次操作$x$之前,注意到仅有$c_{x}$较小,显然成立
2.下一次操作$x$时,由于恒有$c_{x}\le c_{y}$,即在该组解中改为操作$c_{y}$也合法,进而与1.相同
3.下一次操作$x$之后,两者$c_{i}$均相同,显然成立
综上,再根据引理归纳即得证
同时,上述贪心也等价于不断选择最小的$j$操作(归纳$c_{1}\le c_{2}\le ...\le c_{n}$即可证明)
显然操作方式唯一,不妨枚举操作方式(即每一次操作的$j$)并统计序列数:
操作$c_{j}$时对应的$b_{i}$范围为$(c_{j-1},c_{j}]$,即有$c_{j}-c_{j-1}$种方式将$c_{j}$减1
换言之,将每一次(操作前)的$c_{j}-c_{j-1}$相乘后即为序列数(特别的,约定$c_{0}=0$)
进一步的,考虑这样一个构造:
有$n+1$个格子(编号为$[0,n]$),初始$0$上有$k$个球(编号为$[1,k]$),每次操作将一个球向右移动一格,执行此操作$nk$次使所有球均在$n$上的所有方案
记$c_{i}$为$[0,i)$这些格子上球的数量,初始$c_{i}$均为$k$,将$i$上的球向右移动即将$c_{i}$减1,且有$c_{i}-c_{i-1}$种方式,最终使得$c_{i}$均为0的所有方案
不难发现,这与amazing的序列计数是相同的,不妨考虑这个构造的问题:
不考虑$b_{pos}=val$的限制,显然这个问题的答案(也即amazing的序列总数)为${nk\choose n,n,...,n}$(共$k$个$n$)
关于$b_{pos}=val$的限制,对应于此问题中,即第$nk-pos+1$次操作必须选择第$val$个球操作(从左向右数,同一个格子内的球按照编号从小到大排序)
枚举对应的位置$i$,再枚举$i$左侧/上/右侧的球数量$x,y$和$z$(要求$x+y+z=k$且$x<val\le x+y$),选择球的方案数即${k\choose x,y,z}$,同时操作的方案数即
$$
\sum_{\begin{array}&u_{1},u_{2},...,u_{x}<i\\v_{1},v_{2},...,v_{z}>i\\\sum u_{j}+\sum v_{j}+iy=nk-pos\end{array}}
{nk-pos\choose u_{j},v_{j},i,i,...,i}
{pos-1\choose n-u_{j},n-v_{j},n-i-1,n-i,n-i,....,n-i}
$$
(其中左侧$i$的数量为$y$,右侧$n-i$的数量为$y-1$)
将累加的部分展开,提取常数项后也即$\prod_{j=1}^{x}\frac{1}{u_{j}!(n-u_{j})!}\prod_{j=1}^{z}\frac{1}{v_{j}(n-v_{j})!}$
用$f_{i,j,k}$表示选择$j$个$[0,i)$之间的数$x$和为$k$的$\prod \frac{1}{x!(n-x)!}$之和,进而该式也即
$$
\sum_{s=0}^{(i-1)x}f_{i,x,s}f_{n-i,y,s+iy+nz-nk+pos}
$$
关于$f_{i,j,k}$的转移,考虑枚举最后一个数,显然即
$$
f_{i,j,k}=\sum_{x=0}^{i-1}\frac{f_{i,j-1,k-x}}{x!(n-x)!}
$$
预处理$f_{i,j,k}$的复杂度为$o(n^{3}k^{2})$,对于确定的$pos$和$val$计算$f(pos,val)$的复杂度为$o(n^{2}k^{3})$,由于有$n^{2}k$组,因此总复杂度为$o(n^{4}k^{4})$,无法通过
进一步的,注意到$s$的枚举中,后式仅取决于$i,x,z$和$iy+nz-nk+pos$,预处理复杂度为$o(n^{3}k^{4})$,然后即可$o(1)$求出,单次复杂度降为$o(nk^{2})$,总复杂度降为$o(n^{3}k^{4})$(预处理),可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 25 4 #define M 405 5 #define ll long long 6 int n,m,mod,fac[M],inv[M],mi[N][N],f[N][N][M<<1],g[N][N][N][M<<1]; 7 int calc(int pos,int val){ 8 int ans=0; 9 for(int i=0;i<n;i++) 10 for(int x=0;x<val;x++) 11 for(int y=val-x;x+y<=m;y++){ 12 int z=m-x-y,d=i*y+n*z-n*m+pos,s=g[i][x][z][d+n*m]; 13 s=(ll)s*fac[m]%mod*inv[x]%mod*inv[y]%mod*inv[z]%mod; 14 s=(ll)s*mi[i][y]%mod*mi[n-i][y-1]%mod; 15 s=(ll)s*fac[n*m-pos]%mod*fac[pos-1]%mod*inv[n-i-1]%mod; 16 ans=(ans+s)%mod; 17 } 18 return ans; 19 } 20 int main(){ 21 scanf("%d%d%d",&n,&m,&mod); 22 fac[0]=inv[0]=inv[1]=1; 23 for(int i=1;i<M;i++)fac[i]=(ll)fac[i-1]*i%mod; 24 for(int i=2;i<M;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; 25 for(int i=1;i<M;i++)inv[i]=(ll)inv[i-1]*inv[i]%mod; 26 for(int i=0;i<=n;i++){ 27 mi[i][0]=1; 28 for(int j=1;j<=m;j++)mi[i][j]=(ll)mi[i][j-1]*inv[i]%mod; 29 } 30 for(int i=0;i<=n;i++)f[i][0][0]=1; 31 for(int i=1;i<=n;i++) 32 for(int j=1;j<=m;j++) 33 for(int k=0;k<=n*m;k++) 34 for(int x=0;x<i;x++) 35 if (x<=k)f[i][j][k]=(f[i][j][k]+(ll)inv[x]*inv[n-x]%mod*f[i][j-1][k-x])%mod; 36 for(int i=0;i<n;i++) 37 for(int x=0;x<=m;x++) 38 for(int z=0;x+z<=m;z++) 39 for(int d=-n*m;d<=n*m;d++){ 40 int ans=0; 41 for(int s=max(-d,0);s<=(i-1)*x;s++)ans=(ans+(ll)f[i][x][s]*f[n-i][z][s+d])%mod; 42 g[i][x][z][d+n*m]=ans; 43 } 44 for(int pos=1;pos<=n*m;pos++){ 45 for(int val=1;val<=m;val++)printf("%d ",calc(pos,val)); 46 putchar('\n'); 47 } 48 return 0; 49 }View Code
标签:nk,复杂度,pos,Splitting,枚举,le,操作,Creative,atAGC055F 来源: https://www.cnblogs.com/PYWBKTDA/p/15674590.html