1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| 你的思路是**完全正确的**: 本质是对「每个数字出现次数 ≤ 3,且总位数 = 18」的**多重集排列计数**,再用**容斥(扣掉前导 0)**即可。
下面我先把数学逻辑简要梳理清楚,然后给你一份**可直接编译运行的 C++(使用 `__int128`,预处理组合数/阶乘)**。
---
## 数学建模(与你思路一致)
设 [ c_0, c_1, \dots, c_9 \in {0,1,2,3}, \quad \sum_{d=0}^9 c_d = 18 ]
### 1️⃣ 不考虑前导 0 的排列数
对固定的计数方案 ((c_0,\dots,c_9)),排列数是多项式系数:
[ \text{all} = \frac{18!}{\prod_{d=0}^9 c_d!} ]
### 2️⃣ 扣除前导 0(若 (c_0 \ge 1))
固定第一位为 0,剩余 17 位排列:
[ \text{bad} = \frac{17!}{(c_0-1)! \prod_{d=1}^9 c_d!} ]
### 3️⃣ 合法数量
[ \text{valid} = \begin{cases} \text{all}, & c_0 = 0 \ \text{all} - \text{bad}, & c_0 \ge 1 \end{cases} ]
---
## 实现要点
* 枚举 10 个数字,每个取值 `0..3` * DFS / 递归枚举,剪枝 `sum > 18` * 预处理 `0..18` 的阶乘(`__int128`) * 累加答案
---
## C++ 实现(使用 `__int128`)
|