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 公交线路的更多相关文章

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

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

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

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

  3. 洛谷 P3204 [HNOI2010]公交线路

    题面 luogu 题解 矩阵快速幂\(+dp\) 其实也不是很难 先考虑朴素状压\(dp\) \(f[i][S]\) 表示最慢的车走到了\(i\),\([i, p+i-1]\)的覆盖情况 状态第一位一 ...

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

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

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

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

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

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

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

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

  8. bzoj2004 [Hnoi2010]Bus 公交线路 矩阵快速幂+状压DP

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2004 题解 如果 \(N\) 没有那么大,考虑把每一位分配给每一辆车. 假设已经分配到了第 \ ...

  9. bzoj 2004: [Hnoi2010]Bus 公交线路

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

随机推荐

  1. thinter图形开发界面

    tkinter编程步骤 导入Tkinter 创建控件 import thinter 创建主窗口 #win = tkinter.Tk() 设置标题 win.title("xiaoxin&quo ...

  2. hdu 6852Path6(最短路+最小割)

    传送门 •题意 有n个城市,标号1-n 现花费最小的代价堵路 使得从1号城市到n号城市的路径边长 (注意只是变长不是最长) 堵一条路的代价是这条路的权值 •思路 在堵路以前,从1到n的最小路径当然是最 ...

  3. IAP升级

    一.IAP原理 1.在正常情况下,程序运行路流程: 和STM32类似,STM8内部闪存(FLASH)地址起始于 0x8000(STM32是0x08000000),一般情况下,程序文件就从此地 址开始写 ...

  4. python OrderedDict

    15年16年接触python时候,还不知道这个函数,只知道dict的无序,造成了一些麻烦 今天view 代码,发现了 OrderedDict() 在python2.7中比较吃内存 pop(获取指定ke ...

  5. requests + bs4 爬取豌豆荚所有应用的信息

    1.分析豌豆荚的接口的规律 - 获取所有app的接口url 2.往每一个接口发送请求,获取json数据 解析并提取想要的数据 app_data: 1.图标 app_img_url 2.名字 app_n ...

  6. JVM探秘:垃圾收集算法

    本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 垃圾收集算法 垃圾收集算法主要有标记-清除算法.复制算法.标记-整理算法.分代收集算法 ...

  7. vux中x-input在安卓手机输入框的删除按钮(@on-click-clear-icon)点击没反应

    首先看你自己的的版本好,如果在2.6.9以上,我是在git上找到的解决办法,记录一下,希望可以帮到有需要的小伙伴. 在项目中找 node_modules > vux > x-input & ...

  8. Win7旗舰版仅供测试支持正版

    系统效果展示 安装后唯一标准的桌面截图:(如发现安装后与本图不一致,均为第三方安装工具捆绑所为,请注意使用工具!慎用XX桃.XX菜.uXX之类的工具,建议使用推荐的方法安装) 如此清新简洁的安装界面, ...

  9. Java防锁屏小程序

    为防止系统桌面自动锁屏,只需打成jar包,写个批处理程序start.bat,双击执行保持dos窗口执行即可,无其他影响. 程序设计为每30秒动一次鼠标,可根据需要调整. 附代码: package ma ...

  10. python防止字符串转义

    部分转自:https://www.cnblogs.com/hellofengying/p/10183057.html 今天再打开文件名时,出现了错误,如下: In []: path='D:\Code\ ...