1 条题解

  • 0
    @ 2025-5-31 14:57:29
    #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
    上传者