题目链接: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;
}