• [bzoj2004] 公交线路


    题意:有n个公交车站,相邻站之间的距离为1km,有k辆公交车,1-k号站作为起始站,(n-k+1)-n作为终点站,每个站台必须且只能被一辆车经过,车只能从编号小的车站开往编号大的车站,一辆车一次最多开pkm,求所有车从起点站开往终点站的方案数

    题解:

    状压+矩阵快速幂

    最原始的dp:dp[i][s]+=dp[j][s']

    由于公交车的行驶距离不超过p,所以一定存在一个p位的状态能将k辆车表示出来

    由于p和k很小,考虑状压

    我们将所有可能的状态暴搜出来,并且发现这个可以用矩阵转移

    然后构造转移矩阵,为了不重复计数,我们钦定每次只能移动第p位上的车然后判定两个状态之间能否转移(若何判定见代码注释)

    然后转移矩阵转移(n-k)次(i从1到n-k+1),最后乘上初始矩阵即可

    复杂度:O(log(n-k)*(C(9,4)^3))

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #define ll long long
     8 #define mo 30031
     9 #define lowbit(o) (o&(-o))
    10 using namespace std;
    11 
    12 int n,k,p,cnt;
    13 int g[130][130],v[130],bin[30];
    14 
    15 struct Mat {
    16   int v[130][130];
    17   inline void mul(Mat x) {
    18     memset(g,0,sizeof(g));
    19     for(int i=1; i<=cnt; i++)
    20       for(int j=1; j<=cnt; j++)
    21     for(int k=1; k<=cnt; k++)
    22       (g[i][j]+=(v[i][k]*x.v[k][j])%mo)%=mo;
    23     memcpy(v,g,sizeof(g));
    24   }
    25 }ans,b;
    26 
    27 int gi() {
    28   int x=0,o=1; char ch=getchar();
    29   while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    30   if(ch=='-') o=-1,ch=getchar();
    31   while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    32   return o*x;
    33 }
    34 
    35 void qpow(Mat &x, int y) {
    36   Mat ret;
    37   for(int i=1; i<=cnt; i++) ret.v[i][i]=1;
    38   while(y) {
    39     if(y&1) ret.mul(x);
    40     x.mul(x),y>>=1;
    41   }
    42   x=ret;
    43 }
    44 
    45 void dfs(int now, int num, int sta) {
    46   if(num==k) {
    47     v[++cnt]=sta;
    48     return;
    49   }
    50   for(int i=now-1; i>=1; i--) {
    51     dfs(i,num+1,sta+bin[i-1]);
    52   }
    53 }
    54 
    55 void pre() {
    56   for(int i=1; i<=cnt; i++)
    57     for(int j=1; j<=cnt; j++) {
    58       int x=(v[i]<<1)^bin[p]^v[j];//v[i]<<1表示车的相对位置改变了,这样才能判定是否能转移到其他可行状态
    59       if(x==lowbit(x))//判断是否只有p位上的车移动了
    60     b.v[i][j]=1;
    61     }
    62 }
    63 
    64 int main() {
    65   n=gi(),k=gi(),p=gi(),bin[0]=1;  
    66   for(int i=1; i<=20; i++) bin[i]=bin[i-1]<<1;
    67   dfs(p,1,bin[p-1]);
    68   pre();
    69   qpow(b,n-k);
    70   ans.v[1][1]=1;
    71   ans.mul(b);
    72   printf("%d", ans.v[1][1]);
    73   return 0;
    74 }
  • 相关阅读:
    v-bind绑定属性样式——class的三种绑定方式
    vue知识点15
    iOS开发——heightForHeaderInSection设置高度无效
    iOS开发——AFNetworking基于https的使用
    iOS开发——循环遍历的比较
    iOS开发——Block使用小结
    iOS开发——GCD总结
    iOS开发者中心重置设备列表
    iOS开发—— Couldn't add the Keychain Item
    iOS——扬声器与听筒的切换
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7605439.html
Copyright © 2020-2023  润新知