题目
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[pos][sta][pre][sum]代表第pos位, sta 1代表前面已有13 0反之,pre代表前一位是否为1,sum代表前面数值对13取余的结果。
因为sum的当前值决定了后面有多少个满足余数为0的数,所以要加上sum这一维度,sta和pre合成一个维度判断也可。
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
ll dp[20][2][2][14];
int dig[20];
ll dfs(int pos, int sta, int pre, int sum, int limit){
if(pos == -1) return sta && !sum ? 1:0;
if(!limit && dp[pos][sta][pre == 1][sum] != -1) return dp[pos][sta][pre == 1][sum];
int up = limit? dig[pos]:9;
ll ans = 0;
for(int i = 0; i <= up; i++){
ans += dfs(pos-1, sta||(pre == 1 && i == 3), i, (sum*10+i)%13, limit && i == up);
}
if(!limit) dp[pos][sta][pre == 1][sum] = ans;
return ans;
}
ll slove(ll x){
int pos = 0;
while(x){
dig[pos++] = x%10;
x /= 10;
}
ll ans = dfs(pos-1, 0, 0,0, 1);
return ans;
}
int main(){
int n;
memset(dp, -1, sizeof(dp));
while(~scanf("%d", &n)){
printf("%I64d\n", slove(n));
}
return 0;
}