[HNOI 2010]Bus 公交线路
Description
有 \(N\) 个车站, \(K\) 条公交线路。第 \(1\) 到 \(K\) 站是这 \(K\) 线路的起点站。第 \(N-K+1\) 到 \(N\) 是终点站。车只会从编号小的车站驶向编号大的车站。
要求每个车站恰好只属于一个线路,而且同一个线路相临两站距离不得大于 \(P\) 。求有多少种安排方法。输出答案对 \(30031\) 取余数。
\(1\leq N\leq 10^9,1<K\leq P\leq 10,K<N\)
Solution
不妨抛开前 \(K\) 个车站不看。
我们发现,只要每连续的 \(P\) 个站中,都出现了所有 \(K\) 种公交车,方案就是合法的。
证明:
如果方案不合法,必有一线路有相邻站距离大于 \(P\) ,即这连续 \(P\) 个站中缺少一种公交车。根据逆否命题等价,得证。
由于没有线路车站数的限制, \(P\) 又不大,容易想到状态压缩动态规划:
\(F_{i,S}\) 表示:前 \(i\) 位已经确定完毕,不同公交车最后经停站距 \(i+1\) 的位置的状态为 \(S\) ,此时的方案总数。
由于公交车是无差别的, \(S\) 实际上是 \(K\) 个不同整数的集合。每个元素都是 \(1\) 到 \(P\) 的数。
更进一步,集合 \(S\) 中一定有一个元素 \(1\) ,其余的都是 \(2\) 到 \(P\) 。
所以最大只有 \(C_{P-1}^{K-1}\) 个状态即 \(C_9^5=126\) 这样一来我们容易想到用矩阵乘法来优化递推。
Code
//It is made by Awson on 2018.3.12
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int yzh = 30031, SIZE = (1<<10);
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
int n, k, p, bin[20], cnt, sta[130], fin, mp[1050];
struct mat {
int a[130][130];
mat() {memset(a, 0, sizeof(a)); }
mat(int _a[130][130]) {for (int i = 1; i <= 126; i++) for (int j = 1; j <= 126; j++) a[i][j] = _a[i][j]; }
mat operator * (const mat &b) const {
mat ans;
for (int i = 1; i <= cnt; i++)
for (int j = 1; j <= cnt; j++)
for (int k = 1; k <= cnt ; k++)
ans.a[i][j] = (ans.a[i][j]+1ll*a[i][k]*b.a[k][j]%yzh)%yzh;
return ans;
}
}S, T;
mat quick_pow(mat a, int b) {
mat ans = a; b--;
while (b) {
if (b&1) ans = ans*a;
a = a*a, b >>= 1;
}
return ans;
}
int bitcount(int x) {int ans = 0; while (x) x -= lowbit(x), ++ans; return ans; }
void work() {
read(n), read(k), read(p); bin[0] = 1; for (int i = 1; i < 20; i++) bin[i] = (bin[i-1]<<1);
for (int i = 0; i < bin[p-1]; i++) if (bitcount(i) == k-1) sta[++cnt] = (i<<1|1), mp[i<<1|1] = cnt;
for (int i = 1; i <= cnt; i++) {
if (sta[i] == bin[k]-1) S.a[i][i] = 1, fin = i;
int t = sta[i];
if (t&bin[p-1]) T.a[i][mp[(t-bin[p-1])<<1|1]] = 1;
else for (int x = t; x; x -= lowbit(x)) T.a[i][mp[(t-lowbit(x))<<1|1]] = 1;
}
S = S*quick_pow(T, n-k); writeln(S.a[fin][fin]);
}
int main() {
work(); return 0;
}
[HNOI 2010]Bus 公交线路的更多相关文章
- 【BZOJ2004】[Hnoi2010]Bus 公交线路 状压+矩阵乘法
[BZOJ2004][Hnoi2010]Bus 公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1 ...
- 【BZOJ2004】[HNOI2010]Bus 公交线路
[BZOJ2004][HNOI2010]Bus 公交线路 题面 bzoj 洛谷 题解 $N$特别大$P,K$特别小,一看就是矩阵快速幂+状压 设$f[S]$表示公交车状态为$S$的方案数 这是什么意思 ...
- BZOJ 2004 Bus 公交线路(矩阵)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2004 题意:小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依 ...
- bzoj 2004: [Hnoi2010]Bus 公交线路
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...
- BZOJ2004:[HNOI2010]Bus 公交线路(状压DP,矩阵乘法)
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定 ...
- 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法
题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...
- [bzoj2004] [洛谷P3204] [Hnoi2010] Bus 公交线路
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...
- [BZOJ 2004] [Hnoi2010] Bus 公交线路 【状压DP + 矩阵乘法】
题目链接: BZOJ - 2004 题目分析 看到题目完全不会..于是立即看神犇们的题解. 由于 p<=10 ,所以想到是使用状压.将每个连续的 p 个位置压缩成一个 p 位 2 进制数,其中共 ...
- BZOJ 2004: [Hnoi2010]Bus 公交线路 [DP 状压 矩阵乘法]
传送门 题意: $n$个公交站点,$k$辆车,$1...k$是起始站,$n-k+1..n$是终点站 每个站只能被一辆车停靠一次 每辆车相邻两个停靠位置不能超过$p$ 求方案数 $n \le 10^9, ...
随机推荐
- javaScript设计模式-创建型设计模式
我们大家一听到设计模式就感觉设计模式是一个高端的东西,到底什么是设计模式呢?其实设计模式也就是我们的前辈在写代码的时候遇到的问题,提出的解决方案,为了方便人与人之间的交流,取了个名字,叫做设计模式. ...
- hibernate框架学习笔记9:多对多关系案例
员工与角色案例: 一个员工可以是多种角色(总监,经理),一种角色可以是多个员工(保洁) 这里发现无法使用外键表达关系,多对多总是创建第三张表来维护关系 这张表至少两列,都是外键,分别引用两张表的主键 ...
- 听翁恺老师mooc笔记(13)--类型定义和联合
typedef 虽然我们知道使用struct这个关键字定义一个结构类型,然后可以使用该结构类型定义变量.但是每次要使用的时候都需要带着struct这个关键字,那么如何摆脱这个关键字哪?C语言提供了一个 ...
- 《团队-OldNote-项目总结》
我们小组做的是手机便签的app---OldNote 最开始我们想解决普通手机便签无法进行语音和照片的备忘这一问题,但是由于没有做过拍照和录音的经验怕由于技术原因无法达成目的,就没敢写在需求分析中.当完 ...
- C语言博客作业--字符数组
一.PTA实验作业 题目1:统计一行文本的单词个数 1. 本题PTA提交列表 2. 设计思路 Begin 定义字符型变量ch,pre=' ': 定义整型变量count://用来记录单词个数 count ...
- python控制流 If-else
控制流 If-else 我们处理现实生活中的问题时会做出决定,就像决定买哪种相机或者怎样更好的打篮球.同样我们写计算机程序的时候也要做相同的事情.我们通过 if-else 语句来做决定,我们使 ...
- Flask 学习 八 用户角色
角色在数据库中表示 app/models.py class Role(db.Model): __tablename__='roles' id = db.Column(db.Integer,primar ...
- nyoj 开方数
开方数 时间限制:500 ms | 内存限制:65535 KB 难度:3 描述 现在给你两个数 n 和 p ,让你求出 p 的开 n 次方. 输入 每组数据包含两个数n和p.当n和p都为0 ...
- JAVA_SE基础——63.String类的常用方法
获取方法int length() 获取字符串的长度char charAt(int index) 获取特定位置的字符 (角标越界)int indexOf(String str) 查找子串第一次出现的索 ...
- php最新版本配置mysqli
从官网上下载php后(我下的是php7.2.3版本),本想做个mysql的连接,但是无论怎么配置mysqli扩展,发现mysqli都没法用. 从百度上搜的那些方法都没法用,发现都是一些在php.ini ...