E. Phoenix and Computers
题目传送门
参考资料
题面:
题目大意:
有一排电脑,某台电脑前后两台都开起来的时候就会会自动开。
问把这n台电脑都开起来的方案数。
方案数:容易想到DP。
需要知道的东西:
开k台电脑完全手动开不让他自动开机的次数是
2
k
−
1
2^{k-1}
2k−1。
此处摘录自参考资料的两篇博文。证明过程再次不多赘述。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 444;
ll mod;
ll dp[maxn][maxn], C[maxn][maxn], pow2[maxn];
inline void init() {
for (int i = 0; i < maxn; ++i) {
C[0][i] = 1;
}
for (int i = 1; i < maxn; ++i) {
for (int j = 1; j <= i; ++j) {
C[j][i] = (C[j][i - 1] + C[j - 1][i - 1]) % mod;
}
}
pow2[0] = 1;
for (int i = 1; i < maxn; ++i) {
pow2[i] = pow2[i - 1] * 2 % mod;
}
}
int main() {
ll n;
cin >> n >> mod;
init();
dp[0][0] = 1;
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= n; ++j) {
for (int k = 1; i + k <= n; ++k) {
dp[i + k + 1][j + k] = (dp[i + k + 1][j + k] % mod +
dp[i][j] * C[k][j + k] % mod * pow2[k - 1] % mod) % mod;
//因为涉及随时取mod,所以不能用+=
}
}
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
ans = (ans + dp[n + 1][i]) % mod;
}
cout << ans << endl;
return 0;
}
总结:
看了题解再打还是花了一段时间。