BZOJ1833 [ZJOI2010] count

【问题描述】

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

【输入格式】

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

【输出格式】

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

【输入样例】

1 99

【输出样例】

9 20 20 20 20 20 20 20 20 20

【数据范围】

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

100%的数据中,a<=b<=10^12。

正解:数位DP

解题报告:

只要想清楚就很简单,首先问题肯定是把区间1-b和区间1-(a-1)出现的数码统计出来,相减输出来;暴力一个一个数的统计肯定是会超时的,我们先不管前导0,然后我们把数字分为n位,前n位出现的所有数码次数可以看出全是一样的,f[i]表示前i位出现的数码次数,f[i]=f[i-1]*10+10^(i-1);接下来,如果仍然允许前导0,但将数的上限考虑进来的话,我们只需要从高位向低位计算。设当前为第i位,数字的这一位的数字为k,那么对于那些这一位数字小于 k的数,他们的前i-1位是没有数的大小上限的,每个数字累加k*f(i-1)即可,同时0~k-1的数累加10^(i-1);而对于那些这一位的数字恰 好为k的数,为了不超过上限,应累加前i-1位的数字形成的数+1(全为0); 最后,我们来想一下如何处理不允许前导0的情况,其实我们可以一位一位算,因为前n-1位没有上限,第i位可以直接通过f[i-1]*9算出,再把1-9加上10^(i-1),这样即可保证没算包括前导0的情况。

 1 #include <iostream>
 2 #include <iomanip>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <string>
 8 #include <cstring>
 9 #define RG register
10 #define ll long long
11
12 using namespace std;
13
14 ll f[20],l[10],r[10];
15
16 void solve(ll *x,ll s){
17     if (!s) return;
18     ll k=s,m;RG int w=0,i,j,sum[15];
19     while(k) sum[++w]=k%10,k/=10;
20     for (m=1,i=1; i<w; i++){
21         x[0]+=f[i-1]*9;
22         for (j=1; j<=9; j++) x[j]+=f[i-1]*9+m;
23         m*=10;
24     }
25     k=s-sum[w]*m;
26     for (i=1; i<sum[w]; i++) x[i]+=m;
27     for (i=0; i<=9; i++) x[i]+=f[w-1]*(sum[w]-1);
28     x[sum[w]]+=k+1;
29     for (i=w-1; i; i--){
30         m/=10,k-=sum[i]*m;
31         for (j=0; j<sum[i]; j++) x[j]+=m;
32         for (j=0; j<=9; j++) x[j]+=f[i-1]*sum[i];
33         x[sum[i]]+=k+1;
34     }
35     return;
36 }
37
38 int main(){
39     freopen("input.txt","r",stdin);
40     freopen("output.txt","w",stdout);
41     ll a,b,s;RG int i;
42     f[1]=1;s=10;
43     for (i=2; i<=15; i++) f[i]=f[i-1]*10+s,s*=10;
44     scanf("%lld%lld",&a,&b);
45     for (i=0; i<10; i++) l[i]=r[i]=0;
46     solve(l,a-1),solve(r,b);
47     printf("%lld",r[0]-l[0]);
48     for (i=1; i<=9; i++) printf(" %lld",r[i]-l[i]);
49     printf("\n");
50     return 0;
51 }
时间: 2024-08-27 09:17:59

BZOJ1833 [ZJOI2010] count的相关文章

bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)

1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义f[i][j][k]表示若前i个位置有k个j的此时的全局方案数,然后就可以记忆化搜索了(具体看代码吧) 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath>

bzoj1833: [ZJOI2010]count 数字计数 &amp;&amp; codevs1359 数字计数

bzoj1833 codevs1359 这道题也是道数位dp 因为0有前导0这一说卡了很久 最后发现用所有位数减1~9的位数就okay.....orzczl大爷 其他就跟51nod那道统计1出现次数一样啦 #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; LL read(){ LL ans=0,f=1,c=getchar();

数位DP入门:bzoj1833: [ZJOI2010]count 数字计数

膜拜了一下蔡大神....然后突然想起来一些东西然后就填了一个半年多前的坑= = 人生第一道自己写的数位DP...好吧以前是看题解然后也不知道为什么就过了的>_< 数位DP介绍: http://wenku.baidu.com/link?url=9OS5Ybpw5wx00ahrH8ED2oyIlR1uWwrxT8N4pEg27GgBt2T2hLe4sd_h1rmpY7P0HmeHIEDw9h6_K98dPhhjoMhD2TpKcS8w1X8cC_dkPp_ 接下来是题目地址: http://www

bzoj1833 [ZJOI2010]count 数字计数

题目链接 我是DP弱者!!!我是DP弱者!!!我是DP弱者!!! 调了好久,数位DP好恼火QAQ 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9

[bzoj1833][ZJOI2010][count] (数位dp)

Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次. Sample Input 1 99 Sample Output 9 20 20 20 20 20 20 20 20 20 HINT 30%的数据中,a<=b<=10^6:100%的数据中,a<=b<=10^12. So

BZOJ1833: [ZJOI2010]count 数字计数 (数位dp)

传送门 数位dp... ...大概都是这个套路吧... ... 写这个的时候直接水了一发... ...我也不知道自己写的是不是dp... ... 大概是主要内容和dp关系不大的dp... ... mark代码..细长的代码真是丑啊..换行太频繁了.... 1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm&g

BZOJ1833 [ZJOI2010]count 数字计数 【数学 Or 数位dp】

题目 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 输入格式 输入文件中仅包含一行两个整数a.b,含义如上所述. 输出格式 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次. 输入样例 1 99 输出样例 9 20 20 20 20 20 20 20 20 20 提示 30%的数据中,a<=b<=10^6: 100%的数据中,a<=b<=10^12. 题解 你以为我真的会写数位dp? 首先容斥一下,转化为求小于等于

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】count数字计数 数位DP

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