数位dp--cf96e Horse races

给定k,求[l,r]内lucky number个数。r的范围到1e1000。

1.lucky number是至少存在2个lucky digit的距离小于等于k,并不要求所有都小于等于k。

lucky digit是4和7.

2.lpos的范围也是maxn = 1000 + 5

//f(r) - f(l - 1) == f(r) - f(l) + (l符合) ? 1 : 0

#include <iostream>

#include <cstring>

#include <string>

using namespace std;

const int mod = 1e9 + 7;

typedef long long ll;

const int maxn = 1000 + 5;

int dp[maxn][maxn][2];

int bits[maxn];


int t,k;


ll dfs(int len,int lpos,int fg,bool border)//fgtrue表示,存在2lucky digit距离小于等于k

{

    if(!len) return fg == 1;

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

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

    ll res = 0 ;

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

        if(i == 4 || i == 7)

        {

            res += dfs(len - 1, len, (lpos && lpos - len <= k) | fg, border && i == up);

        }

        else res += dfs(len - 1, lpos, fg, border && i == up);

    }

    res %= mod;

    if(!border) dp[len][lpos][fg] = res;

    return res;

}

ll f(string s)

{

    int len = 0;

    for (int i = s.size() - 1; i >= 0; i --) {

        bits[++ len] = s[i] - '0';

    }

    return dfs(len,0,0,1);

}

bool check(string &s)//

{

    int p = 0;

    for (int i = 1; i <= s.size(); i ++) {

        if (s[i - 1] == '4' || s[i - 1] == '7') {

            if(!p || i - p > k) p = i;

            else if(i - p <= k) return true;

        }

    }

    return false;

}


int main()

{

    cin >> t >> k;

    string l,r;

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

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

        cin >> l >> r;

        ll ans = f(r) - f(l) + (check(l) ? 1 : 0);

        cout << (ans % mod + mod) % mod << endl;//

    }

    return 0;

}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值