牛客寒假算法基础集训营3 G:处女座和小姐姐(三)

题目如下:

最基础的数位dp题目,半年前学的就已经忘得差不多了,比赛的时候写了快两个小时。。。

思路很容易想到,即求0~l-1中符合要求的数,再求0~r中符合要求的数,两个减一下就是区间[l,r]中符合要求的数

我用的是先求出0~n中不含6的个数,减一下就能得到含6的个数,这道题的数位dp只需要两步;

1.先求出dp数组,dp[i][j]的值代表最高位i为j时0~jXXX...包含6的个数,具体的步骤网上有解释,这里不写了

2.从高位到低位逐位计算0到...(a[i+2])(a[i+1])(a[i]-1)XXX...中不含6的数,计算到最低位即可得到0~n-1中不含6的个数,注意到若该位为6则不必则中止,因为计算到该位时已经保证前面的高位已知,高位含有6即不满足条件。

最后按照上面的步骤就能得到结果。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long

using namespace std;
int a[20];
ll dp[20][20];

ll solve(ll x){
    ll tmp = x;
    int len=0;
    ll ans=0;
    while(x){
        a[++len] = x%10;
        x/=10;
    }
    a[len+1]=0;
    for(int i=len;i>=1;i--){
        for(int j=0;j<a[i];j++){
            ans += dp[i][j];
        }
        if(a[i]==6) break;
    }
    return tmp-ans;
}

int main()
{
    long long l,r;
    cin >> l >> r;
    memset(dp,0,sizeof(dp));
    for(int i=0;i<10;i++) dp[1][i] = 1;
    dp[1][6] = 0;
    for(int i=2;i<20;i++)//初始化数位dp数组,计算最高位i为j时从0到i999...中不包含6的个数
        for(int j=0;j<10;j++)
            for(int k=0;k<10;k++)
                if(j!=6 && k!=6) dp[i][j] += dp[i-1][k];
    cout << solve(r+1) - solve(l) << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/TJUxyc/p/10327248.html
今日推荐