HDU 3652 B-number

题目链接:HDU 3652 B-number

题目大意:
([1,n])中含有数字(13)同时能够被(13)整除的数的个数。

题解:
HDU 3555 Bomb做法类似,只是在dp数组上增加一维来表示当前的余数,dfs上增加一个判断余数的步骤,只有余数为(0)同时包含(13)时才符合。

#include <iostream>
#include <cstring>
using namespace std;

int dp[15][15][3], digit[15];  // dp[i][j][k],i表示位数,j表示余数,k表示状态

int dfs(int pos, int mod, int status, bool limit) {
    if (pos <= 0) return mod == 0 && status == 2; // 除尽且含有13
    if (!limit && dp[pos][mod][status]) // 没有限制则用记忆化搜索
        return dp[pos][mod][status];
    int up = limit ? digit[pos] : 9;
    int ans = 0;
    for (int i = 0; i <= up; ++i) {
        int nextMod = (mod * 10 + i) % 13; // 加上这一位之后的余数
        int nextStatus = status;
        if (status == 0 && i == 1) // 高位不含13,添加1
            nextStatus = 1;
        else if (status == 1 && i != 1 && i != 3) // 高位不含13且末尾是1,但添加的不是1或3
            nextStatus = 0;
        else if (status == 1 && i == 3) // 高位不含13且末尾是1,添加的是3
            nextStatus = 2;
        ans += dfs(pos - 1, nextMod, nextStatus, limit && i == up);
    }
    if (!limit) dp[pos][mod][status] = ans;
    return ans;
}

int cal(int x) {
    int cnt = 0;
    while (x) {
        digit[++cnt] = x % 10;
        x /= 10;
    }
    return cnt;
}

int main() {
    int n;
    while (cin >> n) {
        memset(dp, 0, sizeof(dp));
        cout << dfs(cal(n), 0, 0, true) << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/IzumiSagiri/p/14304685.html