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.
13 100 200 1000
1 1 2 2
数位dp的板题。
源代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stdio.h>
typedef long long ll;
using namespace std;
int dp[20][20][3];
int a[20];
ll n;
//status用于表示当前的状态,即数组中的第三维的值。
//若status == 0表示末尾不是1,status == 1 表示末尾是1,status == 2 表示含有13
ll dfs(int pos,int status,int mod,bool limit){
if (pos == 0)
return mod == 0 && status == 2;
if (!limit && dp[pos][mod][status] != -1)
return dp[pos][mod][status];
int up = limit?a[pos]:9;//用于限制防止超出最大值
ll ans = 0;
//此处不需要考虑前导零
for (int i = 0; i <= up; i++){
int modd = (mod*10+i)%13;
int statuss = status;
if(status == 0 && i == 1)
statuss = 1;
if (status == 1 && i != 1)
statuss = 0;
if (status == 1 && i == 3)
statuss = 2;
ans += dfs(pos-1,statuss,modd,limit&&i==up);//套路……
}
if (!limit)
dp[pos][mod][status] = ans;
return ans;
}
ll solve(ll n){
int length = 0;
while (n){
a[++length] = n % 10;
n /= 10;
}
return dfs(length,0,0,1);
}
int main(){
while (scanf("%lld",&n)!=EOF){
memset(a,0,sizeof(a));
memset(dp,-1,sizeof(dp));
printf("%lld\n",solve(n));
}
return 0;
}