[BZOJ2004][Hnoi2010]Bus 公交线路
来源:互联网 发布:cf一直出现网络异常 编辑:程序博客网 时间:2024/04/29 04:42
[Hnoi2010]Bus 公交线路
Description
小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km。 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计线路: 1. 设共K辆公交车,则1到K号站作为始发站,N-K+1到N号台作为终点站。 2. 每个车站必须被一辆且仅一辆公交车经过(始发站和终点站也算被经过)。 3. 公交车只能从编号较小的站台驶往编号较大的站台。 4. 一辆公交车经过的相邻两个站台间距离不得超过Pkm。 在最终设计线路之前,小Z想知道有多少种满足要求的方案。由于答案可能很大,你只需求出答案对30031取模的结果。
Input
仅一行包含三个正整数N K P,分别表示公交车站数,公交车数,相邻站台的距离限制。N<=10^9,1 < P<=10,K < N,1 < K<=P
Output
仅包含一个整数,表示满足要求的方案数对30031取模的结果。
Sample Input
样例一:10 3 3
样例二:5 2 3
样例三:10 2 4
Sample Output
1
3
81
Solution
首先在任意一个长度为p的区间里每个公交车都至少要停一次,因此对于一个站台i来说,我们只需要考虑它往后长度为p的区间的公交车停站状态(1/0表示停/不停),每个状态都恰好有k个1
为了保证每个站都有车停,我们不考虑最左位为0的状态,强制令最左位为1,即i这个站有车停(否则转移时我们将允许某一站被跨越)
进而我们又发现对于当前某一个状态S,如果我们随意移动公交车(移动过程始终合法),采取同一种方案到达某一个状态S’时该方案会被重复计数(比如S到S’需要1号公交车前移3,2号公交车前移4,如果随意移动,无论两个前移谁先谁后,最后都会到达S’,而这是同一种方案,因为每一种公交车经过的站是一样的,但在S’被计数了两次),因此我们每次只移动第i个车站的车,即最落后的一辆车(上面我们也已经强制这里有车了)
至于状态S能不能转移到S’,只要两个状态只有一个位置不一样就行了(这个不一样的是第i辆车移动之后造成的结果)
进而我们又发现对于不同的i状态S与状态S’的转移矩阵都一样,因此我们可以矩阵乘法加速
Code
#include <bits/stdc++.h>using namespace std;#define rep(i, l, r) for (int i = (l); i <= (r); i++)#define per(i, r, l) for (int i = (r); i >= (l); i--)#define MS(_) memset(_, 0, sizeof(_))#define PB push_back#define MP make_pair#define debug(...) fprintf(stderr, __VA_ARGS__);typedef long long ll;typedef pair<int, int> PII;template<typename T> inline void read(T &x){ x = 0; T f = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); } while (isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); } x *= f;}const int N = 210;const int MAXP = 30;const ll MOD = 30031;struct Matrix{ ll m[N][N]; Matrix() { MS(m); }}ans, t;int bin[MAXP], n, K, P, cnt = 0, S[N];Matrix operator *(Matrix a, Matrix b){ Matrix c; rep(i,1,cnt)rep(j,1,cnt)rep(k,1,cnt) c.m[i][j] += a.m[i][k]*b.m[k][j]; rep(i,1,cnt)rep(j,1,cnt) c.m[i][j] %= MOD; return c;}Matrix operator ^(Matrix a, int b){ Matrix res; rep(i, 1, cnt) res.m[i][i] = 1; for (; b; b>>=1, a=a*a) if (b&1) res=res*a; return res;}inline void dfs(int dep, int state, int last){ if (dep > K){ S[++cnt] = state; return; } per(i, last-1, 1) dfs(dep+1, state+bin[i-1], i);} inline void build_matrix(){ rep(i, 1, cnt) rep(j, 1, cnt){ int x = (S[i]<<1)^bin[P]^S[j]; if (__builtin_popcount(x) == 1) t.m[i][j] = 1; }}int main(){ bin[0] = 1; rep(i, 1, 20) bin[i] = bin[i-1]<<1; read(n); read(K); read(P); dfs(2, bin[P-1], P); build_matrix(); ans.m[1][1] = 1; Matrix T = t^(n-K); ans = ans * T; printf("%d\n", ans.m[1][1]); return 0; }
- 【HNOI2010】【BZOJ2004】Bus 公交线路
- [BZOJ2004][Hnoi2010]Bus 公交线路
- 【bzoj2004】[Hnoi2010]Bus 公交线路
- 2004: [Hnoi2010]Bus 公交线路
- BZOJ 2004: [Hnoi2010]Bus 公交线路
- bzoj 2004: [Hnoi2010]Bus 公交线路
- BZOJ 2004 [Hnoi2010]Bus 公交线路
- [BZOJ2004][HNOI2010]公交线路(状压DP+矩阵乘法)
- [BZOJ]2004: [Hnoi2010]Bus 公交线路 状态压缩DP+矩阵乘法
- bzoj 2004: [Hnoi2010]Bus 公交线路 状压dp+矩阵乘法
- bzoj2004 Bus公交路线
- bzoj 2004 【hnoi2010】公交线路
- [BZOJ2004]公交线路 DP+矩阵快速幂
- 【hnoi2010】
- [BZOJ 2004][HNOI 2010]Bus 公交线路(矩阵快速幂加速DP)
- bus
- BUS
- bus
- 几个关键字
- codeforces 659E New Reform
- hdu Problem 1242 Rescue bfs + 优先队列
- 事务及并发控制(锁,死锁,恢复)
- 专题一总结 贪心算法
- [BZOJ2004][Hnoi2010]Bus 公交线路
- hibernate多对一或一对多映射——单向
- 截图片和保存图片
- 常规功能和模块自定义系统 (cfcmms)—036模块记录(数据)的权限设计(1)
- 机器学习算法汇总:人工神经网络、深度学习及其它
- 兰顿蚂蚁
- linux 总线 设备 驱动
- 数据库视图和临时表
- 专题一 Problem K