1 条题解
-
0
问题分析
我们需要计算:
$$\left( \sum_{i=0}^\infty \mathrm{C}_{nk}^{ik + r} \right) \bmod p $$其中 ,,不能直接计算组合数。
核心思想:组合意义 + 矩阵快速幂
1. 组合意义转化
设 ,原式等价于:
- 从 个物品中选取若干物品
- 要求选取的物品数模 等于
即:
$$\sum_{j \equiv r \ (\text{mod } k)} \mathrm{C}_{m}^{j} $$2. 动态规划模型
定义状态:
$$f[i][x] = \text{从前 } i \text{ 个物品中选取,物品数模 } k = x \text{ 的方案数} $$状态转移:
- 不选第 个物品:
- 选第 个物品:
即:
3. 矩阵形式
将状态向量记为:
$$\mathbf{A}_i = \begin{pmatrix} f[i][0] \\ f[i][1] \\ \vdots \\ f[i][k-1] \end{pmatrix} $$则:
其中 是 的转移矩阵:
- (不选)
- (选)
初始状态:
$$\mathbf{A}_0 = \begin{pmatrix} 1 \\ 0 \\ \vdots \\ 0 \end{pmatrix} $$最终答案:
$$\text{ans} = \mathbf{A}_m[r] = (M^m \cdot \mathbf{A}_0)[r] $$算法详解
数据结构
typedef long long ll1; ll1 mod; const int N = 105; ll1 n, k, r; ll1 m; // m = n*k ll1 tmp[N]; ll1 A[N]; // 当前结果向量 ll1 B[N]; // 转移矩阵的幂算法步骤
步骤1:初始化
void init() { scanf("%lld%lld%lld%lld", &n, &mod, &k, &r); m = n * k; // 总物品数 n = k; // 复用n作为模数k // B: 转移矩阵对应的多项式(循环卷积) B[0] = B[1] = 1; // 对应 x^0 + x^1 // A: 初始状态向量 A[0] = 1; // f[0][0] = 1 if (n == 1) // k=1的特殊情况 B[0]++; // x^0系数变为2 }为什么 B[0]=B[1]=1?
- 转移方程:
- 用多项式表示:
- 这里 对应系数 [1, 1, 0, ..., 0]
步骤2:循环卷积乘法
void Mul(ll1 *a, ll1 *b, ll1 *c) { for (int i = 0; i < n; i++) { tmp[i] = 0; for (int j = 0; j < n; j++) { (tmp[i] += a[j] * b[(n + (i - j)) % n] % mod) %= mod; } } for (int i = 0; i < n; i++) c[i] = tmp[i]; }循环卷积原理:
- 在模 意义下,
- 乘法:
- 这等价于 矩阵乘法,但用循环卷积实现更高效
步骤3:快速幂计算
void work() { for (; m; m >>= 1) { if (m & 1) { Mul(A, B, A); // A = A * B } Mul(B, B, B); // B = B * B } ll1 ans = A[r]; printf("%lld\n", ans); }快速幂原理:
- 计算
- 初始为 1(对应 )
- 每次将 平方,需要时乘到 上
- 时间复杂度:
正确性证明
定理1:多项式表示
设 ,则:
证明:
- 归纳法:
- 因为 ,所以是循环卷积
定理2:答案提取
是 中 的系数,即:
复杂度分析
时间复杂度
- 循环卷积乘法:
- 快速幂: 次乘法
- 总复杂度:
- 由于 ,,完全可行
空间复杂度
- 存储多项式和临时数组
示例分析
样例1
n=2, p=10007, k=2, r=0- 计算
- 模 :
- 化简:
- 的系数为 8
样例2
n=20, p=10007, k=20, r=0- 计算
- 用快速幂计算,得到系数和模 10007 为 176
算法优势
- 高效: 处理
- 巧妙:将组合数求和转化为多项式问题
- 简洁:代码简短,核心仅两个函数
- 通用:适用于任意模数
特殊情况处理
k=1 的情况
当 时:
- 转移矩阵变为 ?实际上 时只有模 1 的余数 0
- 转移:
- 对应多项式:
- 代码中特殊处理:
if (n == 1) B[0]++
总结
本题的核心技巧:
- 组合转化:将组合数求和转化为模 计数问题
- 多项式表示:用循环卷积表示模 的递推
- 快速幂优化: 计算
通过将组合问题转化为代数问题,利用循环卷积和快速幂,高效解决了大数据范围下的组合数求和问题。
- 1
信息
- ID
- 5760
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者