【BZOJ2004】公交线路(动态规划,状态压缩,矩阵快速幂)

【BZOJ2004】公交线路(动态规划,状态压缩,矩阵快速幂)

题面

BZOJ

题解

看到\(k,p\)这么小
不难想到状态压缩
看到\(n\)这么大,不难想到矩阵快速幂

那么,我们来考虑朴素的\(dp\)
设\(f[i][j]\)表示当前位置为\(i\),前面的\(P\)个位置的状态为\(j\)
其中,状态的含义是某个公交线路最后的停靠站
如果是最后的停靠站就是\(1\),否则是\(0\)

那么,任意状态中只存在\(k\)个\(1\)
并且表示\(i\)的二进制位一定是\(1\)
所以状态相当于最多只会有\(120\)个左右

考虑转移,
每次相当于从原来的状态中,
把一个\(1\)放到了当前位置
其他的依次向左挪一个位置
那么,如果两个状态之间满足这个关系,就可以转移

我们发现转移之和后面的\(j\)有关
所以矩阵快速幂就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MOD 30031
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int n,K,P;
int zt[1<<11],ss,mp[1<<11];
struct Dalao
{
    int s[150][150];
    void init(){memset(s,0,sizeof(s));}
    void pre()
        {
            init();
            for(int i=1;i<=ss;++i)s[i][i]=1;
        }
}zsy;
Dalao operator*(Dalao a,Dalao b)
{
    Dalao ret;ret.init();
    for(int i=1;i<=ss;++i)
        for(int j=1;j<=ss;++j)
            for(int k=1;k<=ss;++k)
                ret.s[i][j]=(ret.s[i][j]+a.s[i][k]*b.s[k][j]%MOD)%MOD;
    return ret;
}
Dalao fpow(Dalao a,int b)
{
    Dalao s;s.pre();
    while(b){if(b&1)s=s*a;a=a*a;b>>=1;}
    return s;
}
int ws(int x){int ret=0;while(x)++ret,x-=x&(-x);return ret;}
bool check(int a,int b)
{
    if(ws((a<<1)&b)!=K-1)return false;
    return true;
}
int main()
{
    n=read();K=read();P=read();
    for(int i=0;i<(1<<P);++i)
        if((i&1)&&ws(i)==K)zt[++ss]=i;
    for(int i=1;i<=ss;++i)
        for(int j=1;j<=ss;++j)
            if(check(zt[i],zt[j]))
               zsy.s[j][i]=1;
    zsy=fpow(zsy,n-K);
    printf("%d\n",zsy.s[1][1]);
    return 0;
}

原文地址:https://www.cnblogs.com/cjyyb/p/8434235.html

时间: 2024-08-02 21:34:23

【BZOJ2004】公交线路(动态规划,状态压缩,矩阵快速幂)的相关文章

点头OJ 1033 . 骨牌覆盖 V2 ( 状态压缩 + 矩阵快速幂 )

做题感悟:先前做过一个类似的题,是俄罗斯的一道区域赛的题目,也是用的状态压缩 + 矩阵快速幂. 解题思路:状态压缩 + 矩阵快速幂 构造一个矩阵 B [ i ] [ j ] 代表状态 i ,与状态 j 是否合法,j 代表上一行的状态,如果合法为 1 ,否则为 0 ,这样如果再得到初始各种状态的方案数的矩阵 A ,A 只有一列 ,这样 B * A 就是第二行各种状态对应 的方案数 .这样再加上矩阵快速幂就解决了. 代码: #include<iostream> #include<sstrea

软件能力认证题---拼图(状态压缩DP+矩阵快速幂)

题意: 给定n*m的棋盘(1<=N<=10^15, 1<=M<=7),用L型骨牌(田字型任意去掉一个口)完全覆盖它,问有多少种解. 思路:m的范围只有1<=M<=7,显然状压DP.但是N的最大值到10^15,只能用快速幂了. 状态表示:0代表此处留空,1代表此处被填满.01序列压缩成一个int型来表示一行的填放情况.(例如:状态为4,则代表100,即第一列填满,第二第列三空) 边界条件: 其中, t = 2^M  代表将前i-1行填满,且第i行放置了状态s时的总方案数.

『公交线路 状压dp 矩阵乘法加速』

公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计线路: 1.设共K辆公交车,则1到K号站作为始发站,N-K+1到N号台作为终点站. 2.每个车站必须被一辆且仅一辆公交车经过(始发站和终点站也算被经过). 3.公交车只能从编号较小的站台驶往编号较大的站台. 4.一辆公交车经过的相邻两个 站台间距离不得超过Pkm. 在最终设计

BNUOJ 34985 Elegant String 2014北京邀请赛E题 动态规划 矩阵快速幂

Elegant String Time Limit: 1000msMemory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,-, k

poj 3744 Scout (Another) YYF I - 概率与期望 - 动态规划 - 矩阵快速幂

(Another) YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties, (Another) YYF is now at the start of enemy's famous "mine road". This is a very long road,

[题解][SHOI2013]超级跳马 动态规划/递推式/矩阵快速幂优化

这道题... 让我见识了纪中的强大 这道题是来纪中第二天(7.2)做的,这么晚写题解是因为 我去学矩阵乘法啦啦啦啦啦对矩阵乘法一窍不通的童鞋戳链接啦 层层递推会TLE,正解矩阵快速幂 首先题意就是给你一个 n 行m 列 的格子图 一只马从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行. 题意很简单暴力dp的思路也很简单但是数据很恶心虽然远古一点,但毕竟是省选题 1 ≤ n ≤ 50,2 ≤ m ≤ 10^9 不过还是给了我们一点提示:n这么小? 总之我们先找出转移式对于每一个点

矩阵快速幂的一份小结

矩阵真是个好东西!虽然矩乘的复杂度有点难看... ... 这几天也做了不少矩阵题目,还是有几道好题目的.不过我打算从入门开始. 矩阵乘法:A[i][k]*B[k][j]=C[i][j];(A的第i行的每项依次乘以B的第j列的每项的和) 很显然这是一个n^3的算法,还是比较难看的. 代码就差不多是这样了. struct Matrix{int T[51][51];}; Matrix Mul(Matrix a,Matrix b,int I,int K,int J) { Matrix S=S0; for

ASC(1)E(矩阵快速幂+简单DP)

Nice Patterns Strike Back Time Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description You might have noticed that there is the new fashion among rich people to have their yards til

HDU 2157 How many ways??(经典矩阵快速幂)

题意:求A经过K个点到B方案数 方法一: 1个0 1 的矩阵 A a[i][j] = 1 表示i 到 j可达 或者说 i 到 j 有1条路 或者说i到j经过一个点的方案数 路可以重复走 而A2 = A* A a[i][j] 的含义是 从i到j经过2个点的方案数 A的k次方 A[i,j]代表 i到j走k步的方案有a[i][j] 矩阵乘法的定义居然和这个模型如此契合,佩服,所以要非常熟悉矩阵乘法的具体步骤才能在这个题目中抽象出矩阵乘法可以正好实现两个定点间的所有可能情况 方法二: 动态规划的思路,状