Todo
打辅助.jpg
抢人头.jpg
抢不到我 当 场 把 键 盘 吃 掉 !
每轮同时填格子和数,然后去绝对值。
$f[i][j][k]$ 表示填了前 $i$ 个数和前 $i$ 个位置,空了 $j$ 个位置同时留了 $j$ 个数(我一开始还打算分两个状态来着),已填的部分产生的权为 $k$ 的方案数。
每次转移:
1.第 $i$ 个数填第 $i$ 个位置:空了 $j$ 个位置同时留了 $j$ 个数,产生权 $0$ ,方案数为 $1$;
2.第 $i$ 个数填前面空的格子,以前留的数填第 $i$ 个位置:空了 $j-1$ 个位置同时留了 $j-1$ 个数,产生权 $i+i$ ,方案数 $j^2$ ;
3.第 $i$ 个数填前面空的格子,第 $i$ 个位置留空:空了 $j$ 个位置同时留了 $j$ 个数,产生权 $i-i$ ,方案数为 $j$ ;
4.遗留第 $i$ 个数,以前留的数填第 $i$ 个位置:空了 $j$ 个位置同时留了 $j$ 个数,产生权 $-i+i$ ,方案数为 $j$ ;
5.遗留第 $i$ 个数,第 $i$ 个位置留空:空了 $j+1$ 个位置同时留了 $j+1$ 个数,产生权 $-i-i$ ,方案数 $1$ 。
#include<bits/stdc++.h> using namespace std; const int N=51; const int Dl=2501; const int P=1e9+7; int f[N][N][2*N*N]; int main() { int n,m,i,j,k; scanf("%d%d",&n,&m); f[0][0][Dl]=1; for(i=1;i<=n;i++) for(j=0;j<i;j++) for(k=-n*n;k<=n*n;k++){ if(j&&k+2*i<=n*n)(f[i][j-1][k+2*i+Dl]+=1ll*f[i-1][j][k+Dl]*j*j%P)%=P; (f[i][j][k+Dl]+=1ll*f[i-1][j][k+Dl]*(2*j+1)%P)%=P; if(k-2*i>=-n*n)(f[i][j+1][k-2*i+Dl]+=f[i-1][j][k+Dl])%=P; } printf("%d",f[n][0][m+Dl]); return 0; }