答题卡是n * n 的,要求出所有的使横竖答题卡对称的涂写方案。
首先,应该看清楚题面给出的条件,横竖答题卡都只能填一个答案,并且横竖答题卡是要对称的。所以横答题卡某一行的答案确定之后,对应的竖答题卡的某一列的答案也就确定了,并且交于这两个答案的行和列也已经确定了
以n = 3可以看到,当将第一行的答案放在第一列的时候,剩下的就是求的答题卡规模为(n - 1) * (n - 1) 的所有方案,当第一行的答案放在第二列的时候,剩下的就是求答题卡规模为(n - 2) * (n - 2) 的所有方案(因为此时根据答案横竖相同要求的对称性,确定了一行的同时也就确定了一列,所以此时有两行和两列都不能进行选择),同理将第一行的答案放在第三列也是一样的。而n = 4的所有情况也是跟n = 3类似。
所以我们可以得出这样的结论:
在棋盘规模为 的情况下,除去将第一行的答案放在第一列之外(这种情况是转化为求(n - 1) * (n - 1)的所有方案数),剩余的情况有(n - 1) 种,并且这(n - 1)种情况都是一样的,都是求棋盘规模为(n - 2) * (n - 2) 的所有方案数。
F(n) = F(n - 1) + (n - 1) * F(n - 2)
- #include
- using namespace std;
- const int MOD = 1000000000 + 7;
- int main() {
- int n;
- cin >> n;
- //res[i]表示i * i的矩阵的方案数目
- vector<long long> res;
- res.emplace_back(1), res.emplace_back(1), res.emplace_back(2);
- for(int i = 3; i <= n; i++) {
- res.emplace_back((res[i - 1] + (((i - 1) % MOD) * (res[i - 2] % MOD))%MOD) % MOD);
- }
- cout << res[n] << endl;
- return 0;
- }
比较经典的多重背包问题
- #include
- using namespace std;
- int dp[3][210];
- int money[3] = {1, 2, 5};
- int main() {
- int n;
- cin>>n;
- for(int i = 0; i <= 200; i++)
- dp[0][i] = 1;
- dp[1][0] = 1, dp[2][0] = 1;
- for(int i = 1; i < 3; i++) {
- for(int j = 0; j <= 200 ; j++)
- if(j >= money[i])
- dp[i][j] = dp[i-1][j] + dp[i][j-money[i]];
- else
- dp[i][j] = dp[i-1][j];
- }
-