[ZJOI2010] 数字计数

题目描述

给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。

输入输出格式

输入格式:

输入文件中仅包含一行两个整数a、b,含义如上所述。

输出格式:

输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

输入输出样例

输入样例#1:

1 99

输出样例#1:

9 20 20 20 20 20 20 20 20 20

说明

30%的数据中,\(a<=b<=10^6;\)

100%的数据中,\(a<=b<=10^{12}。\)

Solution

bzoj1883

数位dp,记忆化搜索

主要就是解释一下变量

len指当前搜到哪一位,当len=0时,就返回当前搜到的值
f表示当前前导0的条件合不合法,初始值是有前导0的,不合法,所以为0
limit表示当前搜索的这一位有没有限制,即不能超过原数这一数位上的数字,1表示有限制,0表示没有
sum表示有多少当前已经统计了多少查找的数字
tq表示当前查找的数字是什么

本来正常情况下,dp数组是要开四维的,\(dp[len][f][limit][sum]\),但是由于本题只在没有前导0以及当前位所有数字都搜满的情况下也就是(\(f\) && \(!limit\)),所以可以省去这两维

提示:关于数组大小,因为我们统计的数字做多只有15位,所以第1维开16即可,第二维因为每次只统计一个数字x,所以最好情况下就是每一位都是x,最多也就是15位,所以也只要开16

Code

#define lol long long
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)

using namespace std;

const int N=20;

lol dp[N][N];
int bit[N];

void in(lol &ans)
{
    ans=0;lol f=1; char i=getchar();
    while(i<'0'||i>'9'){if(i=='-') f=-1; i=getchar();}
    while(i>='0'&&i<='9') ans=(ans<<3)+(ans<<1)+i-'0',i=getchar();
    ans*=f;
}

lol dfs(int len,int f,int limit,lol sum,int tq,lol ans=0) {
    if(!len) return sum;
    if(!limit && f &&  dp[len][sum]!=-1) return dp[len][sum];
    int maxn=limit?bit[len]:9;
    for(int i=0;i<=maxn;i++)
        ans+=dfs(len-1,f||i,limit && i==maxn,sum+((f||i) && (i==tq)),tq);
    if(!limit && f) dp[len][sum]=ans;
    return ans;
}

lol solve(lol a,int tq,int k=0) {
    memset(dp,-1,sizeof(dp));
    while(a) {
        bit[++k]=a%10;
        a/=10;
    }
    return dfs(k,0,1,0,tq);
}
int main()
{
    lol a,b; in(a),in(b);
    for(int i=0;i<10;i++)
        printf("%lld ",solve(b,i)-solve(a-1,i));
    puts("");
    return 0;
}

博主蒟蒻,随意转载.但必须附上原文链接

http://www.cnblogs.com/real-l/

原文地址:https://www.cnblogs.com/real-l/p/9580501.html

时间: 2024-08-30 13:37:15

[ZJOI2010] 数字计数的相关文章

数位dp详解&amp;&amp;LG P2602 [ZJOI2010]数字计数

数位dp,适用于解决一类求x~y之间有多少个符合要求的数或者其他. 例题 题目描述 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众. 不吉利的数字为所有含有4或62的号码.例如: 62315 73418 88914 都属于不吉利号码.但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列. 你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少

题解——[ZJOI2010]数字计数 数位DP

最近在写DP,今天把最近写的都放上来好了,,, 题意:给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 首先询问的是一个区间,显然是要分别求出1 ~ r ,1 ~ l的答案,然后相减得到最终答案 首先我们观察到,产生答案的区间是连续的,且可以被拆分, 也就是说0 ~ 987的贡献= 0 ~ 900 + 901 ~ 987的恭喜, 同理,把位拆开也是等价的,所以我们可以单独计算每个位的贡献 这样讲可能有点不太清晰,举个例子吧 3872 我们先把它按数拆开来

Luogu P2602 [ZJOI2010]数字计数

这算是一道数位DP的入门题了吧虽然对于我来说还是有点烦 经典起手式不讲了吧,\(ans(a,b)\to ans(1,b)-ans(1,a-1)\) 我们首先预处理一个东西,用\(f_i\)表示有\(i\)位数字的时候,每个数字有几个(注意是和).若不考虑前导零,则所有数字都是等价的,转移为: \(f_i=10\cdot f_{i-1}+10^{i-1}\) 这个还是比较好理解的吧,前面一项表示无论这一位放什么直接从前面拿过来已有的,所以这一位可以放\(0\to9\)十个数,后面一项表示当这一位放

【题解】P2602 [ZJOI2010]数字计数

$Description: $ 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. \(Sample\) \(Input:\) 1 99 \(Sample\) \(Output:\) 9 20 20 20 20 20 20 20 20 20 \(Solution:\) 状态 \(f[i][j]\) 表示前 \(i\) 位当前这个数出现了 \(j\) 次 . 那么就可以愉快的dfs了,但是还有一点初始化没懂,暂时得先把他撂下了. #include<bits/

[ZJOI2010]数字计数 理解

题目链接:https://www.luogu.org/problemnew/show/P2602 设d[k][i]为当前情况下选取到第 k 位时数字 i 的数量, sum[k][i]为第 k 位选取 i 时最终的dfa情况数量(能凑成的数字总量)显然 d[k][i]+=d[k+1][i];而对于第 k+1 位不是 i 的数, 也要加上它们的情况(因为第 k 位出现了 1 个 i)所以 d[k][i]+=d[k+i][j](0<=j<=9) 原文地址:https://www.cnblogs.co

P2602 [ZJOI2010]数字计数

题目描述 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 输入输出格式 输入格式: 输入文件中仅包含一行两个整数a.b,含义如上所述. 输出格式: 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次. 输入输出样例 输入样例#1: 1 99 输出样例#1: 9 20 20 20 20 20 20 20 20 20 说明 30%的数据中,a<=b<=10^6: 100%的数据中,a<=b<=10^12. Solution

[ZJOI2010]数字计数 题解

题面 这道题是一道数位DP的模板题: 因为窝太蒟蒻了,所以不会递推,只会记忆化搜索: 首先,咋暴力咋来: 将一个数分解成一个数组,这样以后方便调用: 数位DP的技巧:(用1~b的答案)-(1~a的答案)就是(a~b的答案): 那么对于每个数码i,我们做两次dfs(分别以a为上界和以b为上界): 设正在搜索的数码是digit: 枚举每一位,当这位==digit时,便将答案+1,并记忆化: 然后就没了; 可是这样做忽略了两个重要的事情: 1.可能存在前导零: 2.目前搜到的数比目标值要大: 对于这两

1833: [ZJOI2010]count 数字计数

1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 2951  Solved: 1307[Submit][Status][Discuss] Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次.

BZOJ_1833_[ZJOI2010]_数字计数_(数位dp)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1833 统计\(a~b\)中数字\(0,1,2,...,9\)分别出现了多少次. 分析 数位dp真是细节又多又容易出错,我都懒得看题解,所以也就懒得写题解了... 注意细节吧还是... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 ll a,b; 6 ll A[10],B[10],n