1 条题解
-
0
自动搬运
来自洛谷,原作者为

joke3579
**搬运于
2025-08-24 22:41:55,当前版本为作者最后更新于2023-02-23 15:30:54,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
1.
考虑直接 dp。
设 为当前整数大小为 ,最后一项为 的序列的计数。 容易写出转移:
$$f({i,j}) = \left\{ \begin{aligned} \sum_{t=1}^{k}f({i-j,t}) \qquad j < p \\ \sum_{t=1}^{p-1}f({i-j,t}) \qquad j\ge p \end{aligned} \right.$$直接转移即可做到 ,答案即为 。
Submission.进行状态的压缩。我们发现 这一维实际上只记录了 的情况和 的情况,这可以在转移时完成。然后就可以把这两种状态压缩:
$$f({i,0}) = \sum_{j=1}^{p-1} f({i-j,0}) + f({i-j,1})\qquad f({i,1}) = \sum_{j=p}^{k} f({i-j,0}) $$
设 为当前整数大小为 ,最后一项是否小于 的序列的计数。有转移:答案即为 。直接转移即可做到 。
Submission.2.
可以发现,如上 的转移是线性的,可以写成矩阵乘法的形式。具体地,我们使用 的矩阵进行转移,初始向量记录 段内所有 与 。
例如,当 时矩阵即为:
$$\begin{bmatrix} f({i+1,1})\\ f({i+1,0})\\ f({i,1})\\ f({i,0})\\ f({i-1,1})\\ f({i-1,0})\\ f({i-2,1})\\ f({i-2,0})\\ f({i-3,1})\\ f({i-3,0})\\ \end{bmatrix}= \begin{bmatrix} 0 & 0 & 0 & 0 & 0 &1 & 0 & 1 & 0 & 1\\ 1 & 1 & 1 & 1 & 0 &0 & 0 & 0 & 0 & 0\\ 1 & 0 & 0 & 0 & 0 &0 & 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 &0 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 &0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 1 & 0 &0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 1 &0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 &1 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 &0 & 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 &0 & 0 & 1 & 0 & 0\\ \end{bmatrix} \begin{bmatrix} f({i,1})\\ f({i,0})\\ f({i-1,1})\\ f({i-1,0})\\ f({i-2,1})\\ f({i-2,0})\\ f({i-3,1})\\ f({i-3,0})\\ f({i-4,1})\\ f({i-4,0})\\ \end{bmatrix} $$转移即可。总时间复杂度 。
Submission.3.
你看这个转移矩阵是不是和线性递推的很像?
考虑设 。 我们可以写
$$g(i) = \sum_{j=1}^{p-1}\left( f({i-j,0}) + f({i-j,1})\right) + \sum_{j=p}^{k} f({i-j,0}) = \sum_{j=1}^{p-1} g({i-j}) + \sum_{j=p}^{k} f({i-j,0}) $$前面那部分可以直接扔进线性递推转移。
对于后半部分,考虑在最后一步 时,仅有倒数第二步 的状态能够全部转移。同时,考虑这里的贡献在 时已经被算了,我们只需要 的 。算一下有多少个 满足条件,这就是 对应的系数。
这里由于需要让所有贡献都被算完,线性递推的长度是 的。转移时直接模拟多项式乘法即可,总复杂度为 。Submission.
应用任意模数多项式乘法即可做到 。可能 80% 的部分分是给数组开小的正解准备的。Submission.
#include <bits/stdc++.h> using namespace std; using pii = pair<int,int>; using ll = long long; using ull = unsigned long long; using db = double; using ld = long double; using lll = __int128_t; template<typename T> void get(T & x) { x = 0; char ch = getchar(); bool f = false; while (ch < '0' or ch > '9') f = f or ch == '-', ch = getchar(); while ('0' <= ch and ch <= '9') x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); f && (x = -x); } template <typename T, typename ... Args> void get(T & a, Args & ... b) { get(a); get(b...); } #define rep(i,s,t) for (register int i = (s), i#_ = (t) + 1; i < i#_; ++ i) #define pre(i,s,t) for (register int i = (s), i#_ = (t) - 1; i > i#_; -- i) const int N = 4e3 + 10; const int mod = 20201114; template <typename T1, typename T2> T1 add(T1 a, T2 b) { return (a += b) >= mod ? a - mod : a; }template <typename T1, typename ...Args> T1 add(T1 a, Args ... b) { return add(a, add(b...)); } struct FastMod { int m; ll b; void init(int _m) { m = _m; b = ((lll)1<<64) / m; } FastMod(int _m) { init(_m); } int operator() (ll a) {ll q = ((lll)a * b) >> 64; a -= q * m; if (a >= m) a -= m; return a; } } Mod(mod); int mul(int a, int b) { return Mod(1ll * a * b); } template <typename ...Args> int mul(int a, Args ...b) { return mul(a, mul(b...)); } int k, mx, p, sum[N][2], ans; int f[N], h[N]; ll l; struct seq { int a[N]; int & operator [] (const int & p) { return a[p]; } const int operator [] (const int & p) const { return a[p]; } seq operator * (const seq & b) const { seq ret; rep(i,0,mx-1) ret[i] = 0; rep(i,0,mx-1) rep(j,0,mx-1) ret[i + j] = add(ret[i + j], mul(a[i], b[j])); for (int i = (mx-1) << 1; i >= mx; ret[i] = 0, -- i) rep(j,1,mx) ret[i - j] = add(ret[i - j], mul(ret[i], f[j])); return ret; } } res; seq qp(seq a, ll b) { seq ret; memset(ret.a, 0, sizeof ret.a); ret[0] = 1; while (b) { if (b & 1) ret = ret * a; a = a * a; b >>= 1; } return ret; } int main() { get(k, p, l); mx = k + p - 1; -- l; sum[0][0] = 1; rep(i,1,mx) { rep(j,1,min(p - 1, i)) { sum[i][0] = add(sum[i][0], sum[i - j][0], sum[i - j][1]); } rep(j,p,min(k, i)) { sum[i][1] = (sum[i][1] + sum[i - j][0]) % mod; } } rep(i,1,p-1) f[i] = 1; rep(i,p,k+p-1) rep(j,p,k) if (0 < i - j and i - j < p) ++ f[i]; rep(i,0,k+p-1) h[i] = add(sum[i + 1][0], sum[i + 1][1]); if (l <= mx) { cout << h[l] << endl; return 0; } res[1] = 1; ans = 0; res = qp(res, l); rep(i,0,mx - 1) ans = add(ans, mul(res[i], h[i])); cout << ans << endl; }
- 1
信息
- ID
- 7913
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者