Problem Description
A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.
Input
Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).
Output
Print each answer in a single line.
Sample Input
13
100
200
1000
Sample Output
1
1
2
2
思路:
数位dp。dp[i][j][k]中i表示第i位,j表示第i位之前的数模13的值,k=0表示第i+1位不为1,k=1表示第i+1位为1,k=2表示第i位之前已经发现过13。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n, num[20], dp[20][13][3];
int dfs(int pos, int mod, int state, bool limit)
{
if (pos == -1)
{
return mod == 0 && state == 2;
}
if (!limit && dp[pos][mod][state])
{
return dp[pos][mod][state];
}
int result = 0;
int up = limit ? num[pos] : 9;
for (int i = 0; i <= up; i++)
{
int temp = state;
if (state != 2 && i != 1)
{
temp = 0;
}
if (state == 1 && i == 3)
{
temp = 2;
}
if (i == 1 && state != 2)
{
temp = 1;
}
result += dfs(pos - 1, (mod * 10 + i) % 13, temp, limit && i == up);
}
if (!limit)
{
dp[pos][mod][state] = result;
}
return result;
}
int main()
{
while (~scanf("%d", &n))
{
memset(num, 0, sizeof(num));
memset(dp, 0, sizeof(dp));
int pos = 0;
while (n)
{
num[pos] = n % 10;
n /= 10;
pos++;
}
printf("%d\n", dfs(pos, 0, 0, true));
}
return 0;
}