洛谷P1980 计数问题
因为是NOIp普及组第一题,所以暴力做法当然是可以AC的啦,所以我要写的是一些不一样的东西。
这是我学习编程以来写的第一篇题解o( ̄▽ ̄)ブ
时间复杂度 O(lgn)
(文中所有的位数都按照从左到右的顺序,如第1位是最高位,数“12345”中第1位为1)
零、找规律:
若求所有“四位数” ****(前导零也占位,如0001也是一个“四位数”)中某个非零数x的个数的总和,不难想到有1个x,2个x,3个x,4个x共四种情况。
对于有n个x的情况,x的分布有C(4 n)种,其余位置可用除x外其他数字填充
因此
sum=1 * C(4 1) * 9^(4-1)
+ 2 * C(4 2) * 9^(4-2)
+ 3 * C(4 3) * 9^(4-3)
+ 4 * C(4 4) * 9^(4-4)
不难得出有
推广1:所有“n位数” **…**(n个数字,含前导零)中某个数x的个数总和可表示为 s u m ( n , x ) = ∑ i = 1 n i ( n i ) 9 n − i sum(n,x)=\sum_{i=1}^n i \binom{n}{i} 9^{n-i} sum(n,x)=i=1∑ni(in)9n−i
一、适用于非零x的实现
因此,对于0~N的所有数中x的个数,不妨设有n位的数字N可以写成
a 1 a 2 a 3 . . . a n − 1 a n a_1a_2a_3...a_{n-1}a_n a1a2a3...an−1an则我们可以将这N+1个数分为
( a 1 ∗ 1 0 n − 1 + a 2 ∗ 1 0 n − 2 + . . . + a n − 1 ∗ 1 0 1 + a n ∗ 1 0 0 + 1 ) 个 (a_1*10^{n-1}+a_2*10^{n-2}+...+a_{n-1}*10^1+a_n*10^0+1)个 (a1∗10n−1+a2∗10n−2+...+an−1∗101+an∗100+1)个,
一共n+1组,最后一组只有1个数字,仅包含数字本身
其中,对于第t组 a t ∗ 1 0 n − t a_t*10^{n-t} at∗10n−t个数,前t-1位已经固定为 a 1 a 2 . . . a t − 1 a_1a_2...a_{t-1}