1 条题解
-
0
C. Ayoub and Lost Array 详细题解
问题描述
给定三个整数 、、(,)。求有多少个长度为 的数组 ,满足:
- 对每个 ,有 ;
- 数组所有元素的和能被 整除,即 。
答案对 取模。
问题分析
由于只关心每个元素模 的余数,而不关心具体数值,我们可以将区间 中的数分为三类:模 余 、余 、余 。记这三类数的个数分别为 、、。那么原问题转化为:从这三类中可重复地选取 个数(顺序有关),使得选出的 个余数之和模 等于 ,求方案数。其中每类有 种不同的数值可选。
因此,我们需要先计算 。
计算模 3 余数的个数
对于任意整数 ,其模 余数 。在区间 内,满足 的整数构成一个等差数列,首项为大于等于 的最小同余数,末项为小于等于 的最大同余数。具体计算方法:
设 ,则满足 的 可表示为 。由 得:
为整数,因此 的最小值为 ,最大值为 。若最小值大于最大值,则 ;否则
$$c_t = \left\lfloor \frac{r-t}{3} \right\rfloor - \left\lceil \frac{l-t}{3} \right\rceil + 1 $$标程中采用循环递增寻找首尾的方法,复杂度 也可接受,但更高效的是直接公式计算。不过由于 最大 ,循环最多 3 次,不影响。
动态规划求解方案数
设 表示已经选择了前 个数,这些数的和模 等于 的方案数()。初始状态 ,表示空数组和为 ,方案数为 。
转移:考虑第 个数,可以选择余数为 的任意一个数,有 种选择。加入后新余数为 ,因此:
$$dp[i+1][(j+add)\bmod 3] \mathrel{+}= dp[i][j] \times c_{add} \pmod{MOD} $$最终答案为 。
时间复杂度与空间复杂度
- 计算 :。
- DP 部分:状态数 ,每个状态转移 次,总时间复杂度 。
- 空间复杂度:可以用滚动数组优化到 额外空间,但标程使用 的二维数组(,约 MB,可行)。
示例验证
示例1
输入:
区间 中的数:。
(余0): →
(余1): →
(余2): →DP:
- :
从 出发:
加余0 →
加余1 →
加余2 → - :
从 (值1):加余0 → ;加余1→;加余2→
从 (值1):加余0→;加余1→;加余2→
从 (值1):加余0→;加余1→;加余2→
累加得 ,输出 ,正确。
示例2
输入:
区间只有 ,余数为 ,所以 。
DP 过程:只能选余2的数,3次后总和余 ,只有 种方案(),输出 。示例3
输入:
输出 ,符合预期。代码实现(标程)
#include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; int main() { int n, l, r; cin >> n >> l >> r; // 统计区间 [l, r] 中模 3 余 0, 1, 2 的数的个数 vector<long long> cnt(3, 0); for (int rem = 0; rem < 3; ++rem) { long long first = l; while (first % 3 != rem) first++; if (first > r) continue; long long last = r; while (last % 3 != rem) last--; cnt[rem] = (last - first) / 3 + 1; } // dp[i][j]: 前 i 个数,总和模 3 为 j 的方案数 vector<vector<long long>> dp(n + 1, vector<long long>(3, 0)); dp[0][0] = 1; for (int i = 0; i < n; ++i) { for (int j = 0; j < 3; ++j) { if (dp[i][j] == 0) continue; for (int add = 0; add < 3; ++add) { int nj = (j + add) % 3; dp[i + 1][nj] = (dp[i + 1][nj] + dp[i][j] * cnt[add]) % MOD; } } } cout << dp[n][0] << endl; return 0; }总结
本题核心在于将数值范围问题转化为模 余数的计数问题,然后利用动态规划求解组合方案数。由于只关心总和模 的结果,状态数被压缩到常数级别,使得 的算法可行。注意数据范围大时使用
long long防止中间乘法溢出,并取模运算。
- 1
信息
- ID
- 6487
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者