题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3652
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
Author
wqb0039
Source
2010 Asia Regional Chengdu Site —— Online Contest
题意:
求0 到n中数字含有13且能被13整除的数目!
PS:
数位DP模板题!
取余时用秦九韶算法!
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL __int64
LL n, dp[25][13][3];
//dp[i][mod][j]:长度为i,余数为mod,状态为j,
int digit[25];
//nstatus: 0:不含13, 1:不含13但末尾是1, 2 :含13
LL DFS(int pos, int mod, int status, int limit)
{
if(pos <= 0) // 如果到了已经枚举了最后一位,并且在枚举的过程中有49序列出现
return status==2 && mod==0;//注意是 ==
if(!limit && dp[pos][mod][status]!=-1) //对于有限制的询问我们是不能够记忆化的
return dp[pos][mod][status];
LL ans = 0;
int End = limit?digit[pos]:9; // 确定这一位的上限是多少
for(int i = 0; i <= End; i++) // 每一位有这么多的选择
{
int nmod = (mod*10+i)%13;
int nstatus = status; // 有点else s = statu 的意思
if(status==0 && i==1)//高位不含13,并且末尾不是1,现在末尾添1返回1状态
nstatus = 1;
else if(status==1 && i!=1 && i!=3)//高位不含13,且末尾是1,现在末尾添加的不是1返回0状态
nstatus = 0;
else if(status==1 && i==3)//高位不含13,且末尾是1,现在末尾添加3返回2状态
nstatus = 2;
ans+=DFS(pos-1, nmod, nstatus, limit && i==End);
}
if(!limit)
dp[pos][mod][status]=ans;
return ans;
}
int cal(LL x)
{
int cnt = 0;
while(x)
{
digit[++cnt] = x%10;
x/=10;
}
digit[cnt+1] = 0;
return cnt;
}
int main()
{
while(~scanf("%I64d",&n))
{
memset(dp,-1,sizeof(dp));
int len = cal(n);
LL ans = DFS(len, 0, 0, 1);
printf("%I64d\n",ans);
}
return 0;
}