HDU3652-B-number

       dp系列中还有一类叫做数位dp,那么今天结合这道HDU3652来看一看数位dp到底是什么。 

B-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
1000
Sample Output
1
1
2
2

题意:找出1~n范围内含有13并且能被13整除的数字的个数。

数位dp一般应用于:

       求出在给定区间[A,B]内,符合条件P(i)的数i的个数。

       条件P(i)一般与数的大小无关,而与数的组成有关。

而且[A,B]通常很大,无法模拟。所以说这种题目看起来跟dp八竿子打不着,但它还真是dp了。

好,关于这道题我们需要使用记忆化深搜来记录状态,配合数位DP来解决,详情看代码。

Code:

#include 
#include
#include  
using namespace std;  
int num[15],dp[15][15][3];//dp[i][j][k]表示 i:数位 j:余数 k:3种操作状况,0:末尾不是1,1:末尾是1,2:含有13  
int dfs(int pos,int mod,int have,int uplim)//uplim记录上限,前三个跟dp数组一样 
{  
    if(pos<=0)return mod==0&&have==2;  
    if(!uplim&&dp[pos][mod][have]!=-1)//没有上限并且已被访问过  
        return dp[pos][mod][have];  
    int k=uplim?num[pos]:9;//假设该位是2,下一位是3,如果现在算到该位为1,那么下一位是能取到9的,如果该位为2,下一位只能取到3  
    int ans=0;  
    for(int i=0;i<=k;i++)  
    {  
        int mod_x=(mod*10+i)%13;//看是否能整除13,而且由于是从原来数字最高位开始算,可以发现事实上这个过程就是一个除法过程  
        int have_x=have;  
        if(have==0&&i==1)have_x=1;//末尾不是1,现在加入的是1,则标记为末尾是1   
        if(have==1&&i!=1)have_x=0;//末尾是1,现在加入的不是1,则标记为末尾不是1 
        if(have==1&&i==3)have_x=2;//末尾是1,现在加入的是3,则标记为含有13  
        ans+=dfs(pos-1,mod_x,have_x,uplim&&i==k);//uplim&&i==k,在最开始,取出的k是最高位,所以如果i比k小,那么i的下一位都可以到达9,而i==k了,最大能到达的就只有num[pos-1]  
    }  
    if(!uplim)dp[pos][mod][have]=ans;  
    return ans;  
}  
int main()  
{  
    int n,len;  
    while(~scanf("%d",&n))  
    {  
        memset(dp,-1,sizeof(dp));  
        len=0;  
        while(n)  
        {  
            num[++len]=n%10;  
            n/=10;  
        }  
        printf("%d\n",dfs(len,0,0,1));  
    }  
    return 0;  
}  

你可能感兴趣的:(=====dp=====,#,数位dp,HDU)