题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3652
题目大意:1~n 中包含13且是13的倍数的数的个数
sol:数位dp模版题
dfs(pos,pre,mo,ok,limit) 表示正在处理第pos位,前一位为pre(用于处理是否含13),对13取模为mo,是否已经包含ok,是否满足边界限制limit的数的个数。
B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7852 Accepted Submission(s): 4629
Problem Description
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
code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 60;
const int mod = 1e9+7;
ll dp[40][10][13][2];
int a[maxn];
ll dfs(int pos,int pre,int mo,bool ok,bool limit){
if(pos==-1) {
if(ok&&mo==0) return 1;
else return 0;
}
if(!limit&&dp[pos][pre][mo][ok]!=-1) return dp[pos][pre][mo][ok];
ll ans=0;
int up=limit?a[pos]:9;
for(int i=0;i<=up;i++){
if(pre==1){
ans=ans+dfs(pos-1,i,(mo*10+i)%13,ok||(i==3),limit&&i==up);
}else {
ans=ans+dfs(pos-1,i,(mo*10+i)%13,ok,limit&&i==up);
}
}
if(!limit) {
dp[pos][pre][mo][ok]=ans;
}
return ans;
}
ll sol(ll x){
int pos=0;
while(x){
a[pos++]=x%10;
x/=10;
}
return dfs(pos-1,0,0,false,true);
}
int main(){
ll n;
memset(dp,-1,sizeof(dp));
while(scanf("%lld",&n)==1){
ll ans=sol(n);
printf("%lld\n",ans);
}
return 0;
}