【DP 好题】hihoCoder #1520 古老数字

题目链接

这道题的要点是状态转移的顺序。
要从低位向高位进行状态转移。

Implementation

    string s;
    cin >> s;
    reverse(all(s));
    int x, y;
    scan(x, y);
    int n = (int) s.size();
    vector<vector<short>> dp(n, vector<short>(x, -1));
    vector<int> ten(n);

    ten[0] = 1 % x;

    for (int i = 1; i < n; i++) {
        ten[i] = ten[i - 1] * 10 % x;
    }

//    println(ten);

    auto update = [](short &x, short y) {
        if (x == -1) x = y;
    };

    if (s[0] != '?') {
        dp[0][(s[0] - '0') * ten[0] % x] = s[0] - '0';
    } else {
        if (n == 1) {
            update(dp[0][0], 0);
        }
        for (short i = 1; i < 10; i++) {
            int r = i % x;
            update(dp[0][r], i);
        }
    }

    rng (i, 0, n - 1) {
        short l, r;
        if (s[i + 1] != '?') {
            l = r = s[i + 1] - '0';
        }
        else {
            l = i == n - 2 ? 1 : 0;
            r = 9;
        }
        for (short d = l; d <= r; ++d) { // 先从小到大枚举第 i + 1 位上的数字
            rng (j, 0, x) { // 再枚举 0 到 i 这些位上贡献的余数
                if (dp[i][j] != -1) {
                    int R = (j + d * ten[i + 1]) % x;
                    update(dp[i + 1][R], d);
                }
            }
        }
    }

    if (dp[n - 1][y] == -1) {
        println("No solution");
    } else {
        int r = y;
        down(i, n - 1, 0) {
            cout << dp[i][r];
            r -= dp[i][r] * ten[i] % x;
            if (r < 0) r += x;
        }
        cout << endl;
    }
posted @ 2019-09-25 19:23  Pat  阅读(175)  评论(0编辑  收藏  举报