[bzoj2004] [洛谷P3204] [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
HINT###
【样例说明】
样例一的可行方案如下: (1,4,7,10),(2,5,8),(3,6,9)
样例二的可行方案如下: (1,3,5),(2,4) (1,3,4),(2,5) (1,4),(2,3,5)
P<=10 , K <=8
想法##
emm这个题还是有难度的。
我想到的第一版dp为
\(f[i][st']+=f[i-1][st]\)
f[i][st]中的st为八进制p位数,表示哪些公交车经过 (i-p+1) 到 i 这连续p个站台
由于公交车相邻两者站台间距离不超过p,所以st中应出现所有公交车。
转移时注意st'与st必须满足st的后p-1位与st'的前p-1位相同。
这样是正确的。但显然时间空间都承受不了。
考虑原先的dp有哪些东西是不必要的。
注意到我们转移的时候,从st到st',并没有用到经过某一站台的公交车编号是多少,只关心st与st'是否合法(即是否出现所有公交车)以及是否可以成功转移。
那么把st变为一个二进制p位数,其中某x位上的1代表有一个公交车在这p个站台中最后经过的站台为x
只要st中有k个1,且最后一位为1便是合法的。
从st到st',只要st的后p-1位与st'的前p-1位至多有一位不同便可以成功转移。
但这样状态为\(2^p\),仍有点多。
不过可以发现满足条件的st必须有k个1且最后一位为1,这样状态数就减为了 \(C_{p-1}^{k-1}\),最多也就二百多。
之后就可以矩阵快速幂了。
代码##
细节还是有的,二进制位运算的地方要注意一些。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define P 30031
using namespace std;
const int SZ=260;
int tot;
struct matrix{
int a[SZ][SZ];
matrix() { memset(a,0,sizeof(a)); }
void init() { for(int i=0;i<tot;i++) a[i][i]=1; }
matrix operator * (const matrix &b) const{
matrix c;
for(int i=0;i<tot;i++)
for(int j=0;j<tot;j++)
for(int k=0;k<tot;k++)
(c.a[i][j]+=a[i][k]*b.a[k][j])%=P;
return c;
}
matrix operator *= (const matrix &b) { return *this=*this*b; }
};
matrix Pow_mod(matrix x,int y){
matrix ret; ret.init();
while(y){
if(y&1) ret*=x;
x*=x;
y>>=1;
}
return ret;
}
int n,p,k;
int num[1030];
int cal(int x){
int ret=0;
while(x){
ret+=(x&1);
x>>=1;
}
return ret;
}
void getnum(){
for(int i=0;i<(1<<p);i++)
if(cal(i)==k && (i&1)==1) num[tot++]=i;
}
bool check(int x,int y){
if((y&1)==0) return false;
int z=(x%(1<<(p-1)))^(y>>1);
return z==(z&(-z));
}
int main()
{
scanf("%d%d%d",&n,&k,&p);
getnum();
matrix a,b;
for(int i=0;i<tot;i++)
for(int j=0;j<tot;j++)
if(check(num[i],num[j]))
a.a[i][j]++;
b.a[0][0]=1;
a=Pow_mod(a,n-k); /**/
b=b*a;
printf("%d\n",b.a[0][0]);
return 0;
}
[bzoj2004] [洛谷P3204] [Hnoi2010] Bus 公交线路的更多相关文章
- 【BZOJ2004】[HNOI2010]Bus 公交线路
[BZOJ2004][HNOI2010]Bus 公交线路 题面 bzoj 洛谷 题解 $N$特别大$P,K$特别小,一看就是矩阵快速幂+状压 设$f[S]$表示公交车状态为$S$的方案数 这是什么意思 ...
- 【BZOJ2004】[Hnoi2010]Bus 公交线路 状压+矩阵乘法
[BZOJ2004][Hnoi2010]Bus 公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1 ...
- 洛谷 P3204 [HNOI2010]公交线路
题面 luogu 题解 矩阵快速幂\(+dp\) 其实也不是很难 先考虑朴素状压\(dp\) \(f[i][S]\) 表示最慢的车走到了\(i\),\([i, p+i-1]\)的覆盖情况 状态第一位一 ...
- 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: [Hnoi2010]Bus 公交线路
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2004 状压dp+矩阵乘法. f[i][s]表示从第i位至前面的i-k位,第i位必须取的状态. ...
- [Bzoj2004][Hnoi2010]Bus 公交线路(状压dp&&矩阵加速)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2004 看了很多大佬的博客才理解了这道题,菜到安详QAQ 在不考虑优化的情况下,先推$dp ...
- bzoj2004 [Hnoi2010]Bus 公交线路 矩阵快速幂+状压DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2004 题解 如果 \(N\) 没有那么大,考虑把每一位分配给每一辆车. 假设已经分配到了第 \ ...
- bzoj 2004: [Hnoi2010]Bus 公交线路
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...
随机推荐
- JQ ajaxFileUpload的一些问题
1.input之后没法再次获得响应事件,change无效 解决办法,对file这个Input的父级做响应事件. <div class="lineBox lineBox0_24 line ...
- 面试中常考的字符串操作方法大全,包含ES6
原文链接:http://caibaojian.com/js-string.html 一.charAt() 返回在指定位置的字符. var str="abc" console.log ...
- Linux环境下安装mysql(远程连接),zookeeper,java,tomcat.
环境阿里云centos7.5 64位 + FinalShell + Navicat Permium 12 用到的压缩包(版本看后缀) 注意:安装均在/usr/local目录下,下面代码中#号不要复制上 ...
- supported platform
Target name Platform Architecture Endianness Developer(s) Known Issues/Notes adm5120 Infineon/ADMtek ...
- Delphi中的Val函数和iif函数(出错的时候,会有索引值)
在delphi中Val是一个将字符串转换为数字的函数,Val(S; var V; var Code: Integer)第一个参数是要转换的字符串,第二个参数存放转换后的数字,可以是整数或浮点数,第三个 ...
- 洛谷$P2469\ [SDOI2010]$ 星际竞速 网络流
正解:网络流 解题报告: 传送门$QwQ$ 题目好长昂,,,大概概括下就说有$m$条单向边,$n$个点,每条边有一条边权,每个点有一个点权,然后问每个点都要到达一遍的最小代价是多少$QwQ$? 发现有 ...
- 洛谷P1832 A+B Problem(再升级) 题解 完全背包方案计数
题目链接:https://www.luogu.com.cn/problem/P1832 题目大意: 给定一个正整数n,求将其分解成若干个素数之和的方案总数. 解题思路: 首先找到所有 \(\le n\ ...
- 「UVA10810」Ultra-QuickSort 解题报告
题面 看不懂?! 大概的意思就是: 给出一个长度为n的序列,然后每次只能交换相邻的两个数,问最小需要几次使序列严格上升 不断读入n,直到n=0结束 思路: 交换相邻的两个数,这不就类似冒泡排序吗?但是 ...
- 1093 字符串A+B (20 分)C语言
给定两个字符串 A 和 B,本题要求你输出 A+B,即两个字符串的并集.要求先输出 A,再输出 B,但重复的字符必须被剔除. 输入格式: 输入在两行中分别给出 A 和 B,均为长度不超过 10^6的 ...
- 分享在开发多终端使用比较多的Adb命令
分享在开发多终端或者涉及PC-Android的传输使用比较多的Adb命令 查看连接的设备 adb devices 列出设备安装的软件包 adb shell pm list packages 使用这个方 ...