数(组)位(合)d(数)p(学) 经典题
题目描述
你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数。比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等。
现在给定一个数,问在这个数之前有多少个数。(注意这个数不会有前导0).
输入格式
只有1行,为1个整数n.
输出格式
只有整数,表示N之前出现的数的个数。
Inputs and Outputs examples
Inputs’ e.g. #1
1 | 1020 |
Outputs’ e.g. #1
1 | 7 |
数据范围
n的长度不超过50,答案不超过$2^{63}-1$.
分析
这玩意为什么要被放到数位dp的试炼场里……
观察题意,我们可以做一个微小的联想--把一个数中的一个0
删除相当于把这个0
挪到这个数的最前面.
那么题目也就转化成,统计一个数的全排列中比此数小的数的个数.
我们可以模仿数位dp中验证最大值限制时的做法,考虑用$num[i] \quad i \in [0,9]$来统计这个数中$0 - 9$的出现次数.
首先我们从最高位开始填数,设最高位填了数$j$,那么num[j]--
.
然后我们从$0$开始填,其方案数为$\binom{n - 1}{num[0]}$
然后开始填$1$,这时候只有$n - 1 - num[0]$个位置了,方案数为$\binom{n - num[0] - 1}{num[1]}$
依次类推,我们根据乘法原理可以得到答案为:
$$\prod_{i=0}^9 \binom{n - 1 - \sum_{j=0}^i num_j}{num_i}$$
具体细节可以康康代码.
代码
1 | /* Headers */ |