数位dp--hdu3652 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).

求1到n内,出现13并且能被13整除的数的个数。


#include <iostream>

#include <cstring>

using namespace std;

int bits[12];

int dp[12][13][2][2];


int dfs(int len,int rem,bool occur13,bool state,bool border)//第len位,之前的余数rem,是否已经出现过13,之前一位是不是1,是否在边界

{

    if(!len) return rem == 0 && occur13 ? 1 :0;

    if(!border && dp[len][rem][occur13][state] != -1) return dp[len][rem][occur13][state];

    int res = 0,up = border ? bits[len] : 9;

    for (int i = 0; i <= up; i ++) {//要找的就是有13的数字,所以不能像不要62那样,不继续递归,相反,还要记录是否已经出现了13,如果已经出现,之后就不需要继续找13

        res += dfs(len - 1, (rem * 10 + i) % 13, occur13 || (state && i == 3),i == 1, border && i == up);

    }

    if(!border) dp[len][rem][occur13][state] = res;

    return res;

}

int getbits(int n)

{

    int len = 0;

    while(n)

    {

        bits[++len] = n % 10;

        n /= 10;

    }

    return len;

}

int f(int n)

{

    return dfs(getbits(n),0,0,0,1);

}

int main()

{

    int n;

    memset(dp, -1, sizeof(dp));

    while (cin >> n) {

        cout << f(n) << endl;

    }

    return 0;

}


附上不要62的代码做对比。

#include <iostream>

#include <cstring>

using namespace std;

const int maxn = 25;

int bits[maxn];

int dp[8][2];


int dfs(int len,bool state,bool border)//边界

{

    if(!len) return 1;

    if(!border && dp[len][state] != -1) return dp[len][state];

    int res = 0,up = border ? bits[len] : 9;

    for (int i = 0; i <= up; i ++) {

        if(i == 4 || (i == 2 && state)) continue;//因为不希望有462,所以如果出现,就不继续递归了

        res += dfs(len - 1, i == 6, border && i == up);

    }

    if(!border) dp[len][state] = res;//在不处于边界时计数,因为边界仅仅一个数。

    return res;

}

int getbits(int a)

{

    memset(bits, 0, sizeof(bits));

    int cnt = 0;

    while (a) {

        bits[++ cnt] = a % 10;

        a /= 10;

    }

    return cnt;

}

int f(int a)

{

    return dfs(getbits(a),0,1);

}

int main()

{

    int n,m;

    memset(dp, -1, sizeof(dp));

    while (cin >> n >> m) {

        if(n == 0 && m == 0) return 0;

        cout << f(m) - f(n - 1) << endl;

    }

    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值