HDU 3652 (数位dp)

B-number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8301    Accepted Submission(s): 4921

 

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

具体参考 HDU 2089, 链接: https://blog.csdn.net/no_o_ac/article/details/81134180

#include<cstdio>
#include<cstring>
using namespace std;

int dp[15][15][3];    // 由判断是否整除,是否含有特定子串,以及枚举位数, 自然想到需要 三维数组
                      //dp[i][j][k],i表示位数, j表示模13
                      //k == 0 末尾不是1, k == 1 末尾是1, k == 2 含有13
int a[15];

int dfs(int pos,int mod,int have,bool limit){
    if(pos == -1) return mod == 0 && have == 2;
    if(!limit && dp[pos][mod][have] != -1) return dp[pos][mod][have];
    int up = limit ? a[pos] : 9;
    int tmp = 0,mod_x,have_x;
    for(int i = 0;i <= up;i ++){
        mod_x = (mod * 10 + i) % 13;
        have_x = have;
        if(have == 0 && i == 1) have_x = 1;
        if(have == 1 && i != 1) have_x = 0;
        if(have == 1 && i == 3) have_x = 2;
        tmp += dfs(pos-1,mod_x,have_x,limit && i == up);
    }
    if(!limit) dp[pos][mod][have] = tmp;
    return tmp;
}

int slove(int x){
    int pos = 0;
    while(x){
        a[pos++] = x % 10;
        x /= 10;
    }
    return dfs(pos-1,0,0,true);
}

int main(){
    int n;
    memset(dp,-1,sizeof(dp));
    while(~scanf("%d",&n)){
        printf("%d\n",slove(n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/no_o_ac/article/details/81138549