[Bzoj2004][Hnoi2010]Bus 公交线路(状压dp&&矩阵加速)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2004
看了很多大佬的博客才理解了这道题,菜到安详QAQ
在不考虑优化的情况下,先推$dp$式子,设$dp[i][j]$为最慢的公交车走到了第$i$站,$[i,i+p-1]$站的状态为$j$时的方案数。$i$到$i+p-1$的范围内有且仅有$k$辆车,则状态$j$应该为$p$长度的二进制串,其中有且仅有$k$个$1$(表示$k$辆车)并且第$1$位一定为$1$(第$1$位对应了当前的位置)。则初始态为$dp[0][111(k个1)…000(p-k个0)]$,结束态为$dp[n-k][111(k个1)…000(p-k个0)]$。判断状态$w$是否可以转移到状态$e$,则判断$w$的第$2$位到第$p+1$位($p+1$位补零)是否与$e$的第$1$位到$p$位只有一位不同,是则可以转移$dp[i][e]+=dp[i-1][w]$;
这时候考虑优化,$n<=1e9$就注定要矩阵快速幂加速,则先处理出所有状态之间的关系并构建矩阵$d[i][j]$,$d[i][j]$为$1$表示第一次第$i$个状态可以转移到第$j$个状态。我们要求的是第$n-k$次后初始态到结束态的方案数,根据矩阵乘法的定义$d[i][j]=\sum_{k=1}^{n}d[i][k]*d[k][j]$,则我们只要将矩阵连乘$(n-k)$次,d[结束态][初始态]就是我们所求的。而初始态和结束态实际上是一样的。
当n较小时可以状压dp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = ;
int check(int x) {//判断x状态中1的个数
int sum = ;
while (x) {
sum++;
x -= (x&(-x));
}
return sum;
}
int dp[][ << ];
int main() {
int n, k, p;
while (scanf("%d%d%d", &n, &k, &p) != EOF) {
memset(dp, , sizeof(dp));
int End;
for (int i = ( << (p - )); i < ( << p); i++) {
if (i == ( << p) - - (( << (p - k)) - ))
End = i;
}
dp[][End] = ;
for (int i = ; i <= n - k; i++) {
for (int j = ( << (p - )); j < ( << p); j++) {
for (int w = ( << (p - )); w < ( << p); w++) {
if (check(j) == check(w) && check(j) == k) {
int q = (w - ( << (p - ))) << ;
int t = (q^j);
if (t == (t&(-t))) {
dp[i][j] = (dp[i][j] + dp[i - ][w]) % mod;
}
}
}
}
}
printf("%d\n", dp[n - k][End]);
}
}
本题正解:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = ;
int check(int x) {//判断x中1的个数
int sum = ;
while (x) {
sum++;
x -= (x&(-x));
}
return sum;
}
struct martix {
int tmp[][];
int num;
martix operator *(const martix &b)const {
martix ans;
ans.num = num;
for (int i = ; i <= num; i++) {
for (int j = ; j <= num; j++) {
ans.tmp[i][j] = ;
for (int k = ; k <= num; k++) {
ans.tmp[i][j] += tmp[i][k] * b.tmp[k][j];
ans.tmp[i][j] %= mod;
}
}
}
return ans;
}
};
martix qpow(martix a, int x) {
martix ans;
ans.num = a.num;
memset(ans.tmp, , sizeof(ans.tmp));
for (int i = ; i <= ans.num; i++)
ans.tmp[i][i] = ;
while (x) {
if (x & )
ans = ans * a;
a = a * a;
x /= ;
}
return ans;
}
int statu[ << ];
int main() {
int n, k, p;
while (cin >> n >> k >> p) {
martix a;
int len = , End;
for (int i = ( << (p - )); i < ( << p); i++) {
if (check(i) == k) {
statu[++len] = i;
if (i == ( << p) - - (( << (p - k)) - ))
End = len;
}
}
a.num = len;
memset(a.tmp, , sizeof(a.tmp));
for (int i = ; i <= len; i++) {
for (int j = ; j <= len; j++) {
int q = (statu[j] - ( << (p - ))) << ;
int t = (q^statu[i]);
if (t == (t&(-t)))
a.tmp[i][j] = ;
}
}
a = qpow(a, n - k);
printf("%d\n", a.tmp[End][End]);
}
}
[Bzoj2004][Hnoi2010]Bus 公交线路(状压dp&&矩阵加速)的更多相关文章
- 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调查了市民的需求,决定按下述规则设计 ...
- 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂
[题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...
- 【BZOJ2004】[Hnoi2010]Bus 公交线路 状压+矩阵乘法
[BZOJ2004][Hnoi2010]Bus 公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1 ...
- 『公交线路 状压dp 矩阵乘法加速』
公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的 ...
- BZOJ 2004 公交线路(状压DP+矩阵快速幂)
注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...
- BZOJ2004: [Hnoi2010]Bus 公交线路
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2004 状压dp+矩阵乘法. f[i][s]表示从第i位至前面的i-k位,第i位必须取的状态. ...
- bzoj2004 [Hnoi2010]Bus 公交线路 矩阵快速幂+状压DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2004 题解 如果 \(N\) 没有那么大,考虑把每一位分配给每一辆车. 假设已经分配到了第 \ ...
- HDU 5564 Clarke and digits 状压dp+矩阵加速
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 求长度在[L,R]范围,并且能整除7的整数的总数. 题解: 考虑最原始的想法: dp[ ...
随机推荐
- unkown类型
1,任何类型的值都可以赋给 unkown类型 2. 如果没有类型断言或基于控制流的类型细化时 unknown 不可以赋值给其它类型,此时它只能赋值给 unknown 和 any 类型 3. 如果没有类 ...
- ARM指令集的最新版本包括针对JavaScript的优化
在ARM指令集中,ARMv8.3添加了一个新的float-to-int指令,其错误和超出范围的值按照JavaScript的方式处理.以前[指令]获取JavaScript的语义要慢得多,JavaScri ...
- 洛谷P4003 [国家集训队2017]无限之环 网络流 最小费用最大流
题意简述 有一个\(n\times m\)棋盘,棋盘上每个格子上有一个水管.水管共有\(16\)种,用一个\(4\)位二进制数来表示当前水管向上.右.下.左有个接口.你可以旋转除了\((0101)_2 ...
- Eclipse搭建Maven项目并上传SVN备份
本文出自:http://www.cnblogs.com/2186009311CFF/p/7226127.html 背景:近段时间在学着Java,想着用Java做BS的项目.但是项目一遇到问题又要重做, ...
- ASP.NET的OnClientClick与OnClick事件
OnClientClick是客户端事件方法.一般采用JavaScript来进行处理.也就是直接在IE端运行.一点击就运行. OnClick事件是服务器端事件处理方法,在服务器端,也就是IIS中运行.点 ...
- [luogu]P3939 数颜色[二分]
[luogu]P3939 数颜色 题目描述 小 C 的兔子不是雪白的,而是五彩缤纷的.每只兔子都有一种颜色,不同的兔子可能有 相同的颜色.小 C 把她标号从 1 到 n 的 n 只兔子排成长长的一排, ...
- SpringCloud 教程 (四) docker部署spring cloud项目
一.docker简介 Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机). ...
- [CSP-S模拟测试]:方程的解(小学奥数)
题目描述 给出一个二元一次方程$ax+by=c$,其中$x$.$y$是未知数,求它的正整数解的数量. 输入格式 第一行一个整数$T$,表示有$T$组数据.接下来$T$行,每行$3$个整数$a$.$b$ ...
- [CSP-S模拟测试]:题(DP+数学)
题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...
- Solr单机环境搭建及部署
一.定义 官网的定义: Solr是基于Lucene构建的流行,快速,开放源代码的企业搜索平台.它具有高度的可靠性,可伸缩性和容错能力,可提供分布式索引,复制和负载平衡查询,自动故障转移和恢复,集中式配 ...