DP。dp[i][j]可以表示i行j列满足要求的组合个数,考虑dp[i-1][k]满足条件,那么第i行的那k列可以为任意排列(2^k),其余的j-k列必须全为1,因此dp[i][j] += dp[i-1][k]*(2^k)*C(j, k)。
1 /* 5155 */ 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 6 #define MAXN 51 7 8 const __int64 MOD = 1e9+7; 9 __int64 dp[MAXN][MAXN]; 10 __int64 C[MAXN][MAXN]; 11 __int64 two[MAXN]; 12 13 void init() { 14 int i, j, k, tmp; 15 16 two[0] = 1; 17 for (i=1; i<MAXN; ++i) { 18 two[i] = (two[i-1] << 1); 19 two[i] %= MOD; 20 } 21 22 C[1][0] = C[1][1] = 1; 23 for (i=2; i<MAXN; ++i) { 24 C[i][0] = C[i][i] = 1; 25 for (j=1; j<i; ++j) { 26 C[i][j] = C[i-1][j] + C[i-1][j-1]; 27 C[i][j] %= MOD; 28 } 29 } 30 31 for (i=0; i<MAXN; ++i) 32 dp[i][1] = dp[1][i] = 1; 33 34 for (i=2; i<MAXN; ++i) { 35 for (j=1; j<MAXN; ++j) { 36 dp[i][j] = dp[i-1][j]*(two[j]-1)%MOD; 37 for (k=1; k<j; ++k) { 38 dp[i][j] += dp[i-1][k]*C[j][k]%MOD*two[k]; 39 dp[i][j] %= MOD; 40 } 41 } 42 } 43 } 44 45 int main() { 46 int n, m; 47 48 #ifndef ONLINE_JUDGE 49 freopen("data.in", "r", stdin); 50 freopen("data.out", "w", stdout); 51 #endif 52 53 init(); 54 while (scanf("%d %d", &n, &m) != EOF) 55 printf("%I64d\n", dp[n][m]); 56 57 return 0; 58 }
时间: 2024-10-29 13:20:47