每日一題之 hiho221 Push Button II (計數dp)
描述 There are N buttons on the console. Each button needs to be pushed exactly once. Each time you may push several buttons simultaneously.
Assume there are 4 buttons. You can first push button 1 and button 3 at one time, then push button 2 and button 4 at one time. It can be represented as a string “13-24”. Other pushing way may be “1-2-4-3”, “23-14” or “1234”. Note that “23-41” is the same as “23-14”.
Given the number N your task is to find the number of different valid pushing ways.
輸入 An integer N. (1 <= N <= 1000)
輸出 Output the number of different pushing ways. The answer would be very large so you only need to output the answer modulo 1000000007.
樣例輸入 3 樣例輸出 13
思路:
統計方案數的題目可以用dp來做,不妨我們設dp[i][j]表示 數字 1~i 分成 j 組一共有多少種方案。那麼考慮 dp[i+1][j+1]等於多少? 在之前由於遞推求得了 dp[i][j] 了,那麼
- 一種情況是1~i 的數分成 j 組,然後第 i+1個數 獨立成為一組 ,相當於在分好的 j 組中 插空就行了,j 個組 一共 j+1 個空,所以這種情況的方案數是
- 另外一種情況是 1~i的數已經被分成了 j+1 個組,那麼第 i+1 這個數,隨便放到這 j+1中的任意一個組就行了,那麼這種情況的方案數是
綜上就可以得出遞推式:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1e3+5;
const int mod = 1e9+7;
typedef long long ll;
ll dp[maxn][maxn];
void solve(int n)
{
memset(dp,0,sizeof(dp));
for (int i = 1; i <= n; ++i)
dp[i][1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
dp[i][j] = (dp[i-1][j-1]*j)%mod + (dp[i-1][j]*j)%mod;
dp[i][j] %= mod;
}
}
ll res = 0;
for (int i = 1; i <= n; ++i) {
res = (res + dp[n][i])%mod;
}
cout << res%mod << endl;
}
int main()
{
int n;
cin >> n;
solve(n);
return 0;
}