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; }