数位DP

#include <bits/stdc++.h>

using namespace std;

long long dp[22][10];
int digit[20];

/// 对于一般的数 只要第一个数字确定了 如果成立的话 最后一个数字只有一种情况 所以只能返回0或1
/// 但是对于以0开头而且只有最后一个数字不为0的数而言 也只是加上1这就不正确 少加了8个 

long long DFS(int pos, int begin, int flag)
{
    if(dp[pos][begin] != -1 && !flag)
        return dp[pos][begin];// n 位到 pos 位的数字已经确定 判断这样满足条件的个数 
    int end = flag ? digit[pos] : 9;
    if(pos == 0) return begin <= end;
    long long ans = 0;
    for(int i=0; i<=end; i++)
        ans += DFS(pos-1, begin, i==end && flag);
    if(!flag)
        dp[pos][begin] = ans;
    return ans;
}

long long cal(long long n)
{
    int pos = 0;
    if(!n) return 0;
    while(n)
    {
        digit[pos++] = n%10;
        n /= 10;
    }
    if(pos == 1) return digit[0];

    long long  ans = 0;
    for(int i=0; i<=digit[pos-1]; i++)   
        ans += DFS(pos-2, i, i==digit[pos-1]);
    return ans + 8;
}

int main()
{
    long long  l, r;
    memset(dp, -1, sizeof(dp));
    cin>>l>>r;
    cout<<cal(r) - cal(l - 1)<<endl;
    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值