题目链接:​​B-number​

题目大意:给你一个N,问小于等于N的数里面有多少个B-number,B-number的定义是出现13这个子序列并且数位之和为13的倍数

题目思路:数位dp,有没有13我们可以直接去判断,最后能不能被13整除我们在dfs里面定义一个余数去算就好了,2代表有13,1代表前一位是1,0代表都不是,这样就不用像其他的数位dp那样去给一个pre去判断了

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;
int digit[200],dp[200][14][3];

int dfs(int pos,int mod,int occ,bool limit){
if(pos == -1){
if(mod == 0&occ == 2) return 1;
return 0;
}
if(!limit&&dp[pos][mod][occ] != -1) return dp[pos][mod][occ];
int up = limit?digit[pos]:9;
int ans = 0;
for(int i = 0;i <= up;i++){
int nmod = (mod*10+i)%13;
int nocc = occ;
if(nocc == 1&&i == 3) nocc = 2;
else if(nocc != 2) nocc = (i==1)?1:0;
ans += dfs(pos-1,nmod,nocc,limit&&i == digit[pos]);
}
if(!limit) dp[pos][mod][occ] = ans;
return ans;
}

int solve(int x){
int pos = 0;
while(x){
digit[pos++] = x%10;
x/=10;
}
return dfs(pos-1,0,0,true);
}

int main(){
int n;
memset(dp,-1,sizeof(dp));
while(~scanf("%d",&n)){
printf("%d\n",solve(n));
}
return 0;
}