题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=2004

题解

如果 \(N\) 没有那么大,考虑把每一位分配给每一辆车。

假设已经分配到了第 \(i\) 位,那么想要知道合不合法,我们需要知道每一辆车的上一个停靠点距离现在有多少的距离。考虑直接状压这个东西,发现它的数据量为 \(P_{p}^k\),很大。

但是我们可以发现,每一个位置到底是哪辆车无关紧要,我们只需要知道每个位置有没有车就可以了。于是数据量降低为 \(\binom p{\frac p2}\)。另外,\(0\) 这个距离是必须要选的,这样也可以剪枝掉一些。

于是大概最终的状态数为 \(130\) 左右,可以使用矩阵快速幂来加速。


时间复杂度 \(O(130^3\log n)\)。

  1. #include<bits/stdc++.h>
  2. #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
  3. #define dbg(...) fprintf(stderr, __VA_ARGS__)
  4. #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
  5. #define fi first
  6. #define se second
  7. #define pb push_back
  8. template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
  9. template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
  10. typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
  11. template<typename I> inline void read(I &x) {
  12. int f = 0, c;
  13. while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
  14. x = c & 15;
  15. while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
  16. f ? x = -x : 0;
  17. }
  18. #define lowbit(x) ((x) & -(x))
  19. const int N = 130;
  20. const int NP = (1 << 10) + 7;
  21. const int P = 30031;
  22. int n, p, k, cnt, S, T;
  23. int st[N], s1[NP], mp[NP];
  24. inline int smod(int x) { return x >= P ? x - P : x; }
  25. inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
  26. inline int fpow(int x, int y) {
  27. int ans = 1;
  28. for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
  29. return ans;
  30. }
  31. struct Matrix {
  32. int a[N][N];
  33. inline Matrix() { memset(a, 0, sizeof(a)); }
  34. inline Matrix(const int &x) {
  35. memset(a, 0, sizeof(a));
  36. for (int i = 1; i <= cnt; ++i) a[i][i] = x;
  37. }
  38. inline Matrix operator * (const Matrix &b) {
  39. Matrix c;
  40. for (int k = 1; k <= cnt; ++k)
  41. for (int i = 1; i <= cnt; ++i)
  42. for (int j = 1; j <= cnt; ++j)
  43. sadd(c.a[i][j], a[i][k] * b.a[k][j] % P);
  44. return c;
  45. }
  46. } A, B;
  47. inline Matrix fpow(Matrix x, int y) {
  48. Matrix ans(1);
  49. for (; y; y >>= 1, x = x * x) if (y & 1) ans = ans * x;
  50. return ans;
  51. }
  52. inline void ycl() {
  53. S = (1 << p) - 1;
  54. for (int s = 0; s <= S; ++s) {
  55. if (s) s1[s] = s1[s ^ lowbit(s)] + 1;
  56. if (s1[s] == k && (s & 1)) st[++cnt] = s, mp[s] = cnt;
  57. }
  58. T = mp[(1 << k) - 1];
  59. }
  60. inline void ycl2() {
  61. for (int i = 1; i <= cnt; ++i) {
  62. int s = st[i];
  63. if ((s >> (p - 1)) & 1) A.a[i][mp[((s << 1) & S) | 1]] = 1;
  64. else for (int j = 0; j < p; ++j) if ((s >> j) & 1) A.a[i][mp[((s ^ (1 << j)) << 1) | 1]] = 1;
  65. }
  66. }
  67. inline void work() {
  68. ycl();
  69. ycl2();
  70. B.a[T][1] = 1;
  71. B = fpow(A, n - k) * B;
  72. printf("%d\n", B.a[T][1]);
  73. }
  74. inline void init() {
  75. read(n), read(k), read(p);
  76. }
  77. int main() {
  78. #ifdef hzhkk
  79. freopen("hkk.in", "r", stdin);
  80. #endif
  81. init();
  82. work();
  83. fclose(stdin), fclose(stdout);
  84. return 0;
  85. }

bzoj2004 [Hnoi2010]Bus 公交线路 矩阵快速幂+状压DP的更多相关文章

  1. hihoCoder#1743:K-偏差排列(矩阵快速幂+状压dp)

    题意 如果一个 \(1\to N\) 的排列 \(P=[P_1, P_2, ... P_N]\) 中的任意元素 \(P_i\) 都满足 \(|P_i-i| ≤ K\) ,我们就称 \(P\) 是 \( ...

  2. Codeforces Round #554 (Div. 2) F2. Neko Rules the Catniverse (Large Version) (矩阵快速幂 状压DP)

    题意 有nnn个点,每个点只能走到编号在[1,min(n+m,1)][1,min(n+m,1)][1,min(n+m,1)]范围内的点.求路径长度恰好为kkk的简单路径(一个点最多走一次)数. 1≤n ...

  3. [Bzoj2004][Hnoi2010]Bus 公交线路(状压dp&&矩阵加速)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2004 看了很多大佬的博客才理解了这道题,菜到安详QAQ 在不考虑优化的情况下,先推$dp ...

  4. BZOJ2004: [Hnoi2010]Bus 公交线路

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2004 状压dp+矩阵乘法. f[i][s]表示从第i位至前面的i-k位,第i位必须取的状态. ...

  5. BZOJ2004:[HNOI2010]Bus 公交线路(状压DP,矩阵乘法)

    Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定 ...

  6. 【BZOJ2004】[HNOI2010]Bus 公交线路

    [BZOJ2004][HNOI2010]Bus 公交线路 题面 bzoj 洛谷 题解 $N$特别大$P,K$特别小,一看就是矩阵快速幂+状压 设$f[S]$表示公交车状态为$S$的方案数 这是什么意思 ...

  7. 【BZOJ2004】[Hnoi2010]Bus 公交线路 状压+矩阵乘法

    [BZOJ2004][Hnoi2010]Bus 公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1 ...

  8. 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂

    [题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...

  9. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

随机推荐

  1. java实现js端的escape和unescape

    1.今天遇到这么个问题,需要把一些特殊字符传递到后台进行处理,例如Aa111111!@#,结果到了后台出现了个别字符中文符号了.这个时候需要转码.常见的就是js端的escape和unescape这种函 ...

  2. php key()函数 语法

    php key()函数 语法 作用:返回数组内部指针当前指向元素的键名.大理石构件支架 语法:key(array) 参数: 参数 描述 array 必需.规定要使用的数组. 说明:返回数组内部指针当前 ...

  3. Linux下安装Tomcat(2)

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和 其它一些公司及个人共同开发而成.由于有了Sun的参与和支持,最新 ...

  4. [WC2012]记忆中的水杉树

    https://www.luogu.org/problemnew/show/P4125 题解 首先一开始所有的线段互不相交. 那么对于第二问来说,一定存在一种方法使得所有线段都朝着一个方向动. 比如说 ...

  5. Nexus Repository OSS 3安装配置使用

    Nexus Repository OSS 3是一个开源的仓库管理系统,提供了更加丰富的功能,而且安装.配置.使用起来也更加简单方便.OSS 3版本主要支持的仓库(Repository)包括如下: bo ...

  6. (转)dial tcp 10.96.0.1:443: getsockopt: no route to host --- kubernetes(k8s)DNS 服务反复重启

    转:https://blog.csdn.net/shida_csdn/article/details/80028905 kubernetes(k8s)DNS 服务反复重启解决: k8s.io/dns/ ...

  7. VS code 同步设置与插件

    准备工作:拥有一个github账户,电脑上需安装VSCode.实现同步的功能主要依赖于VSCode插件 "Settings Sync"第一步:安装同步插件Settings Sync ...

  8. Oracle-创建索引分区

    对大数据量索引进行分区同样能够优化应用系统的性能.一般来说,如果索引所对应的表的数据量非常大,比如几百万甚至上千万条数据,则索引也会占用很大的空间,这时,建议对索引进行分区. Oracle索引分区分为 ...

  9. Vue访问子组件实例或子元素

    1 尽管存在 prop 和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件(例如,调用子组件的方法).为了达到这个目的,你可以通过 ref 特性为这个子组件赋予一个 ID 引用 ...

  10. 使用TensorFlow的基本步骤

    学习任务 学习使用TensorFlow,并以california的1990年的人口普查中的城市街区的房屋价值中位数作为预测目标,使用均方根误差(RMSE)评估模型的准确率,并通过调整超参数提高模型的准 ...