number
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 1000Sample Output
1 1 2 2
这是我自己做出的第一道数位DP题
题意:要求数字含有13并且被13整除,所以需要传入每次mod13的结果看最后是否mod13==0,而且每次传入前一位如果前一位是1,并且当前位是3,状态state为1,并且如果状态state为1后之后全是1,最后当状态为1(含有13)并且mod13为0时返回1
我当时wa了好多次,以为dp数组没有记录状态state这一项,因为当时想如果可以满足条件最后的state不应该都是1吗,就没记录,但实际上state的记录最多只能记录到倒数第二位,也就是传进来的state是没有枚举这一位之前数的state,那么当我们枚举最后一位的时候就有可能存在这种情况,之前state全是0.而之前数字最后一位是1,现在你又枚举了3,继续递归发现到最后了,返回上一层递归,这时候储存记录下来的是state为0的情况,所以state应该记录
网上写的我看状态都分了三种,感觉没有必要
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef __int64 ll;
int digit[25];
ll dp[25][10][20][2];
ll dfs(int pos,int pre,int num,int yes,int limit){
if(pos == -1)
return yes && num % 13 == 0;
ll &dpnow = dp[pos][pre][num][yes];
if(!limit && dpnow != -1)
return dpnow;
int max_digit = limit ? digit[pos] : 9;
ll ans = 0;
for(int i = 0; i <= max_digit; i++){
if(yes){
ans += dfs(pos - 1, i, (num * 10 + i) % 13, 1, limit && i == max_digit);
}
else{
ans += dfs(pos - 1, i, (num * 10 + i) % 13, pre == 1 && i == 3, limit && i == max_digit);
}
}
if(!limit)
dpnow = ans;
return ans;
}
ll solve(ll n){
int pos = 0;
while(n){
digit[pos++] = n % 10;
n /= 10;
}
return dfs(pos-1,0,0,0,1);
}
int main(){
ll n;
memset(dp,-1,sizeof(dp));
while(cin >> n){
cout << solve(n) << endl;
}
return 0;
}