1 条题解
-
0
#include <bits/stdc++.h> using namespace std; const int MAXN = 200000; const int MOD = 998244353; int n; // [火柴棒数量][是否进位][上面是否结束][下面是否结束] int dp[MAXN + 5][2][2][2]; // 0~9 对应火柴棒数量 int c[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6}; // add 带 %= 的 += void add(int &a, int &b) { a += b; if (a > MOD) a -= MOD; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n; n -= 4; // 去掉加号与等于号 dp[0][0][0][0] = 1; for (int i = 0; i <= n; i++) for (int j = 0; j <= 1; j++) for (int k = 0; k <= 1; k++) for (int l = 0; l <= 1; l++) { // 由 dp[i][j][k][l] 推后续状态 if (j == 0 && k == 1 && l == 1) continue; // 不能再加数字时直接过滤(没进位且都结束了) if (dp[i][j][k][l] == 0) continue; // 无意义状态直接过滤(方案数为 0) // 如果某行结束了,那行就只能有不算火柴棒的前导零 for (int up = 0; up <= (k == 1 ? 0 : 9); up++) for (int down = 0; down <= (l == 1 ? 0 : 9); down++) { int now = up + down + j; // 进位前的值 int ex = now / 10; // 下一步进位的值 // 先算第三行的火柴棒 int sum = i + c[now % 10]; // 前两行火柴棒只有当不是前导零的时候才算火柴棒 if (k == 0) sum += c[up]; // 第一行的火柴棒 if (l == 0) sum += c[down]; // 第二行的火柴棒 // dp[i][j][k][l] -> dp[sum][ex][0/1][0/1] // flagUp/Down 记录上面/下面能不能结束 // 某行已经结束了、或者还没结束且当前选了非零、或者直接就是没有火柴棒时就可以结束 bool flagUp = k || up != 0 || i == 0; bool flagDown = l || down != 0 || i == 0; if (flagUp && flagDown) // 都可以结束 add(dp[sum][ex][1][1], dp[i][j][k][l]); if (flagUp && l == 0) // 上面可以结束,下面可以不结束 add(dp[sum][ex][1][0], dp[i][j][k][l]); if (k == 0 && flagDown) // 上面可以不结束、下面可以结束 add(dp[sum][ex][0][1], dp[i][j][k][l]); if (k == 0 && l == 0) // 上面可以结束、下面可以结束 add(dp[sum][ex][0][0], dp[i][j][k][l]); } } cout << dp[n][0][1][1]; return 0; }
信息
- ID
- 13436
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 28
- 已通过
- 9
- 上传者