dp[i][j][k] 已选i个人 选到第j层 第j层有k个人
讨论相邻层 上一层选了l人 那么共有 两层之间的方案数 以及这一层自己的方案数
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1e9+7; ll Pow[3605]; ll dp[65][65][65]; ll C[65][65]; int N,K; void debug(){ for(int i = 1; i <= N; ++i) for(int j = 1; j <= 1; ++j) for(int k = 1; k <= N; ++k) printf("dp[%d][%d][%d]=%lld ",i,j,k,dp[i][j][k]); printf(" "); } ll PPow(ll x,int y){ if(x==-1) x += MOD; ll ans = 1; while(y){ if(y&1) ans = ans*x% MOD; y >>= 1; x = x*x %MOD; } return ans; } int Judge(int x,int y,int z){ int tt = x-z; if(y == 1) return tt==0; else if(tt >= y-1) return 1; else return 0; } int main(){ int T; Pow[0]=1; C[0][0]=1; for(int i = 1; i < 65; ++i) for(int j = 0; j <= i; ++j) if(j) C[i][j] = (C[i-1][j]+C[i-1][j-1]) % MOD; else C[i][j] = 1; for(int i = 1; i < 3605; ++i) Pow[i] = Pow[i-1]*2%MOD; scanf("%d",&T); while(T--){ memset(dp,0,sizeof(dp)); scanf("%d %d",&N,&K); N--; for(int j = 1; j < K; ++j) for(int i = 1; i <= N; ++i){ if(j==1) { dp[i][j][i]=C[N][i]*Pow[i*(i-1)/2] % MOD; continue; } for(int k = 1; k <= i; ++k) for(int l = 1; l <= i; ++l){ // printf("%lld ",dp[i][j][k]); if(Judge(i,j,k) && Judge(i-k,j-1,l) ) dp[i][j][k] = (dp[i][j][k] + dp[i-k][j-1][l] * C[N-i+k][k] % MOD * PPow(Pow[l]-1,k) %MOD * Pow[k*(k-1)/2] %MOD ) % MOD; // printf("%d %d %d %d: %lld %lld %lld ",i,j,k,l,dp[i][j][k],C[N-i+k][k],PPow(Pow[l]-1,k) ) ; } } // debug(); ll sum = Pow[N*(N-1)/2]; for(int i = 1; i <= N; ++i) for(int j = 1; j <= K; ++j) for(int k = 1; k <= N; ++k){ // if(sum) printf("%d %d %d ",i,j,k); sum = (sum + dp[i][j][k]*Pow[(N-i)*(N-i-1)/2]) % MOD; } printf("%lld ",sum); } return 0; }