hdu 3652 B-number(数位DP)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yjf3151731373/article/details/52825074


B-number
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

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

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 20;
int dp[N][N][N], dit[N];




int dfs(int len,int mod,int have,int limit)
{
    if(len<=0)
        return mod==0 && have==2;
    if(!limit&&dp[len][mod][have]!=-1)
        return dp[len][mod][have];
    int ans=0, k;
    k=limit?dit[len]:9;




    for(int i=0;i<=k;i++)
    {
        int modx=(mod*10+i)%13, havex=have;
         if(have == 0 && i == 1)//末尾不是1,现在加入的是1
            havex = 1;//标记为末尾是1
        if(have == 1 && i != 1)//末尾是1,现在加入的不是1
            havex = 0;//标记为末尾不是1
        if(have == 1 && i == 3)//末尾是1,现在加入的是3
            havex = 2;//标记为含有13
        ans+=dfs(len-1,modx,havex,limit&&i==k);
    }




    if(!limit)
        dp[len][mod][have]=ans;
    return ans;
}




int solve(int x)
{
    memset(dit,0,sizeof(dit));
    int k=0;
    while(x)
    {
        dit[++k]=x%10;
        x/=10;
    }
    memset(dp,-1,sizeof(dp));
    return dfs(k,0,0,1);
}
int main()
{
    int l;
    while(scanf("%d", &l)!=EOF&&l)
    {
        printf("%d\n",solve(l));
    }
    return 0;
}


借鉴:

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <algorithm>  
  4. using namespace std;  
  5.   
  6. int bit[15];  
  7. int dp[15][15][3];  
  8. //dp[i][j][k]  
  9. //i:数位  
  10. //j:余数  
  11. //k:3种操作状况,0:末尾不是1,1:末尾是1,2:含有13  
  12.   
  13. int dfs(int pos,int mod,int have,int lim)//lim记录上限  
  14. {  
  15.     int num,i,ans,mod_x,have_x;  
  16.     if(pos<=0)  
  17.         return mod == 0 && have == 2;  
  18.     if(!lim && dp[pos][mod][have] != -1)//没有上限并且已被访问过  
  19.         return dp[pos][mod][have];  
  20.     num = lim?bit[pos]:9;//假设该位是2,下一位是3,如果现在算到该位为1,那么下一位是能取到9的,如果该位为2,下一位只能取到3  
  21.     ans = 0;  
  22.     for(i = 0; i<=num; i++)  
  23.     {  
  24.         mod_x = (mod*10+i)%13;//看是否能整除13,而且由于是从原来数字最高位开始算,细心的同学可以发现,事实上这个过程就是一个除法过程  
  25.         have_x = have;  
  26.         if(have == 0 && i == 1)//末尾不是1,现在加入的是1  
  27.             have_x = 1;//标记为末尾是1  
  28.         if(have == 1 && i != 1)//末尾是1,现在加入的不是1  
  29.             have_x = 0;//标记为末尾不是1  
  30.         if(have == 1 && i == 3)//末尾是1,现在加入的是3  
  31.             have_x = 2;//标记为含有13  
  32.         ans+=dfs(pos-1,mod_x,have_x,lim&&i==num);//lim&&i==num,在最开始,取出的num是最高位,所以如果i比num小,那么i的下一位都可以到达9,而i==num了,最大能到达的就只有,bit[pos-1]  
  33.     }  
  34.     if(!lim)  
  35.         dp[pos][mod][have] = ans;  
  36.     return ans;  
  37. }  
  38.   
  39. int main()  
  40. {  
  41.     int n,len;  
  42.     while(~scanf("%d",&n))  
  43.     {  
  44.         memset(bit,0,sizeof(bit));  
  45.         memset(dp,-1,sizeof(dp));  
  46.         len = 0;  
  47.         while(n)  
  48.         {  
  49.             bit[++len] = n%10;  
  50.             n/=10;  
  51.         }  
  52.         printf("%d\n",dfs(len,0,0,1));  
  53.     }  
  54.   
  55.     return 0;  
  56. }  

猜你喜欢

转载自blog.csdn.net/yjf3151731373/article/details/52825074