BZOJ-1833 [ZJOI2010]count 数字计数 数位DP
2017-06-10 20:27
483 查看
大家都很强, 可与之共勉。
1833: [ZJOI2010]count 数字计数Time Limit: 3 Sec Memory Limit: 64 MB
Submit: 3440 Solved: 1518
[Submit][Status][Discuss]
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。
Source
Day1
Day1
显然,我们可以先计算出[1,a-1],[1,b]中每个数字出现的个数,然后相减即可。问题变为:给一个数n,求1,2,…,n中每个数字出现的次数。
以下叙述中,“i位”都是从低位向高位数。
首先,我们允许前导0,也不考虑数大小的上限,在位数一定时,设为i,每种数字出现的次数是相同的,记为f(i)。不难得出递推式f(i)=10*f(i-1)+10^(i-1)(将第i位和前i-1位的数字分开考虑即可)。
继续,如果仍然允许前导0,但将数的上限考虑进来的话,我们只需要从高位向低位计算。设当前为第i位,n的这一位的数字为k,那么对于那些这一位数字小于k的数,他们的前i-1位是没有数的大小上限的,每个数字累加k*f(i-1)即可,同时0~k-1的数累加10^(i-1);而对于那些这一位的数字恰好为k的数,为了不超过上限,应累加前i-1位的数字形成的数+1。
最后,如何处理前导0呢?
其实,假设n有m位,我们只需要先统计出1,2,…m-1位数的情况(而这些是没有上限的,会比较方便),计算时而且保证这些数的首位不为0,然后对于m位同样的在最高位的时候不将0计算进来即可。
#include <cstdio> int num[20] ; long long a, b, f[20], pow[20] ; long long cnta[10], cntb[10] ; inline void Digit_Dp ( long long n, long long* cnt ) { if ( !n ) return ; long long N = n ; int M ; for ( M = 0 ; N ; num[++ M] = N % 10, N /= 10 ) ; for ( int i = 1 ; i < M ; ++ i ) { cnt[0] += f[i - 1] * 9 ; for ( int j = 1 ; j < 10 ; ++ j ) cnt[j] += f[i - 1] * 9 + pow[i - 1] ; } n -= num[M] * pow[M - 1] ; for ( int i = 1 ; i < num[M] ; ++ i ) cnt[i] += pow[M - 1] ; for ( int i = 0 ; i < 10; ++ i ) cnt[i] += f[M - 1] * ( num[M] - 1 ) ; cnt[num[M]] += n + 1 ; for ( int i = M - 1 ; i ; -- i ) { n -= num[i] * pow[i - 1] ; for ( int j = 0 ; j < num[i] ; ++ j ) cnt[j] += pow[i - 1] ; for ( int j = 0 ; j < 10; ++ j ) cnt[j] += f[i - 1] * num[i] ; cnt[num[i]] += n + 1 ; } } int main ( ) { pow[0] = 1 ; for ( int i = 1 ; i < 15 ; ++ i ) { f[i] = f[i - 1] * 10 + pow[i - 1] ; pow[i] = pow[i - 1] * 10 ; } scanf ( "%lld%lld", &a, &b ) ; Digit_Dp ( a - 1, cnta ) ; Digit_Dp ( b, cntb ) ; for ( int i = 0 ; i <= 9 ; ++ i ) printf ( "%lld%c", cntb[i] - cnta[i], ( i ^ 9 ) ? ' ' : '\n' ) ; }
相关文章推荐
- 【bzoj1833】[ZJOI2010]count 数字计数 数位DP
- [bzoj1833][ZJOI2010]count 数字计数——数位dp
- bzoj 1833 [ZJOI2010]count 数字计数(数位DP)
- bzoj1833: [ZJOI2010]count 数字计数(数位dp)
- 【BZOJ1833】【ZJOI2010】count 数字计数 (数位DP)
- 【BZOJ 1833】【ZJOI 2010】[数位DP]count 数字计数
- BZOJ 1833: [ZJOI2010]count 数字计数 数位DP,处理前导0
- BZOJ 1833: [ZJOI2010]count 数字计数 [数位DP]
- BZOJ1833 [ZJOI2010]count 数字计数 【数学 Or 数位dp】
- BZOJ 1833: [ZJOI2010]count 数字计数 【数位DP】
- bzoj1833: [ZJOI2010]count 数字计数 数位dp
- 【BZOJ 1833】 [ZJOI2010]count 数字计数|数位DP
- BZOJ 1833 ZJOI2010 count 数字计数 数位DP
- [bzoj 1833] [ZJOI2010]count 数字计数:数位DP
- BZOJ 1833 ZJOI2010 count 数字计数 数位DP
- BZOJ_1833_[ZJOI2010]count 数字计数_数位DP
- [BZOJ 1833] [ZJOI2010] count 数字计数 【数位DP】
- [省选前题目整理][BZOJ 1833][ZJOI 2010]count 数字计数(数位DP)
- Bzoj1833:[ZJOI2010]count 数字计数:数位dp
- [BZOJ 1833][ZJOI 2010]count数字计数(数位DP)