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

xyz32768
“各方面相差太远”搬运于
2025-08-24 21:46:28,当前版本为作者最后更新于2017-12-10 13:00:23,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
一、问题分析
====== 将问题转化为:一个个数的序列,序列的每个位置需要填充一个范围内的数。同时对于任意的,序列的第个位置已经被填充,填充的数为。同时区间内填充的数必须包含的所有数。而「一辆公交车经过的相邻两个站台间距离不得超过km」这个条件,等价于序列中任意一个长度为的一段,都必须填充有的所有数。
二、DP模型
====== 分析后可以得出,由于前个填充的数已经确定,所以这里只关心序列中的数相同或不相同,而和具体数值无关。因此设为序列中已经填充完,这一段填充的状态为的方案数。是一个长度为的串,从高往低(之后的「第几位」都是从高位往低位)第位为表示位置已经被填充,否则位置还没被填充。
三、DP转移
====== 为了保证每个位置都能被填充,规定在转移过程中,的第位恒为。同时由于区间里必须有填充所有个数,所以再规定在转移过程中必须包含且仅包含个。
而判断能否从转移,就是把最高位的去掉之后在末尾再补一个(记为),如果中的个能够恰好与中个其中个一一对应,,那么能从转移。
四、矩阵优化
====== 考虑到的数据范围,想到矩阵乘法。这时根据上面推出的转移条件,得到有用的状态只有个。可以得到矩阵规模的最大值为。
复杂度。
五、代码
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 134, ZZQ = 30031; int n, K, P, tot, sta[N]; struct cyx { int n, m, a[N][N]; cyx() {} cyx(int _n, int _m) : n(_n), m(_m) {memset(a, 0, sizeof(a));} friend inline cyx operator * (cyx a, cyx b) { int i, j, k; cyx res = cyx(a.n, b.m); for (i = 1; i <= res.n; i++) for (j = 1; j <= res.m; j++) for (k = 1; k <= a.m; k++) (res.a[i][j] += a.a[i][k] * b.a[k][j]) %= ZZQ; return res; } friend inline cyx operator ^ (cyx a, int b) { int i; cyx res = cyx(a.n, a.m); for (i = 1; i <= res.n; i++) res.a[i][i] = 1; while (b) { if (b & 1) res = res * a; a = a * a; b >>= 1; } return res; } } Orz, Zzq; int main() { int i, j, k; cin >> n >> K >> P; for (i = (1 << P - 1); i < (1 << P); i++) { int cnt = 0; for (j = 0; j < P; j++) if ((i >> j) & 1) cnt++; if (cnt == K) sta[++tot] = i; } Orz = cyx(tot, tot); Zzq = cyx(tot, 1); for (i = 1; i <= tot; i++) for (j = 1; j <= tot; j++) { int S1 = sta[i], S2 = sta[j]; S1 = S1 - (1 << P - 1) << 1; for (k = 0; k < P; k++) if (!((S1 >> k) & 1) && S1 + (1 << k) == S2) Orz.a[j][i] = 1; } Zzq.a[tot][1] = 1; Orz = (Orz ^ n - K) * Zzq; cout << Orz.a[tot][1] << endl; return 0; } ====
- 1
信息
- ID
- 2277
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者