zoukankan      html  css  js  c++  java
  • [HNOI2010]BUS 公交线路

    题目描述

    小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km。 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计线路:1.设共K辆公交车,则1到K号站作为始发站,N-K+1到N号台作为终点站。2.每个车站必须被一辆且仅一辆公交车经过(始发站和终点站也算被经过)。 3.公交车只能从编号较小的站台驶往编号较大的站台。 4.一辆公交车经过的相邻两个站台间距离不得超过Pkm。 在最终设计线路之前,小Z想知道有多少种满足要求的方案。由于答案可能很大,你只需求出答案对30031取模的结果。

    输入输出格式

    输入格式:

    仅一行包含三个正整数N K P,分别表示公交车站数,公交车数,相邻站台的距离限制。N<=10^9,1<P<=10,K<N,1<K<=P

    输出格式:

    仅包含一个整数,表示满足要求的方案数对30031取模的结果。

    输入输出样例

    输入样例#1: 复制
    样例一:10 3 3
    样例二:5 2 3
    样例三:10 2 4
    输出样例#1: 复制
    1
    3
    81

    说明

    【样例说明】

    样例一的可行方案如下: (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

    原条件可以转化为任意长为p的连续车站有k种车

    于是状压,令f[i][S],表示前i个车站,前p个车站状态为S

    状态为S的第j位为1表示从i开始,表示那一位是那一种车最靠近i的车站

    那么S为合法的条件为有且只有k位为1

    构造转移矩阵,矩阵快速幂

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 struct Matrix
     8 {
     9   int a[131][131];
    10 }Mat,ans,res;
    11 int cnt,Mod=30031,n,k,p,c[2001],w[2001],s[2001];
    12 Matrix operator*(const Matrix &a,const Matrix &b)
    13 {int i,j,l;
    14   Matrix res;
    15   memset(res.a,0,sizeof(res.a));
    16   for (i=1;i<=cnt;i++)
    17     {
    18       for (j=1;j<=cnt;j++)
    19     {
    20       for (l=1;l<=cnt;l++)
    21         {
    22           res.a[i][j]+=a.a[i][l]*b.a[l][j]%Mod;
    23           if (res.a[i][j]>=Mod)
    24           res.a[i][j]-=Mod;
    25         }
    26     }
    27     }
    28   return res;
    29 }
    30 Matrix qpow(int y)
    31 {int i;
    32   for (i=1;i<=cnt;i++)
    33     res.a[i][i]=1;
    34   while (y)
    35     {
    36       if (y&1) res=res*Mat;
    37       Mat=Mat*Mat;
    38       y>>=1;
    39     }
    40   return res;
    41 }
    42 int main()
    43 {int i,j,x;
    44   cin>>n>>k>>p;
    45   c[0]=0;
    46   for (i=1;i<(1<<p);i++)
    47     {
    48       c[i]=c[i-(i&(-i))]+1;
    49       if (c[i]==k&&(i&(1<<p-1)))
    50     {
    51       w[i]=++cnt;
    52       s[cnt]=i;
    53     }
    54     }
    55   for (i=1;i<=cnt;i++)
    56     {
    57       if (s[i]&1)
    58     {
    59       Mat.a[i][w[(s[i]>>1)|(1<<p-1)]]=1;
    60     }
    61       else
    62     {
    63       for (j=0;j<p;j++)
    64         if (s[i]&(1<<j))
    65         {
    66           Mat.a[i][w[((s[i]^(1<<j))>>1)|(1<<p-1)]]=1;
    67         }
    68     }
    69     }
    70   x=(1<<p)-(1<<(p-k));
    71   ans.a[1][w[x]]=1;
    72   ans=ans*qpow(n-k);
    73   printf("%d
    ",ans.a[1][w[x]]);
    74 }
  • 相关阅读:
    Static了解和复习继承。
    复习篇1.对象和封装
    第一章笔记
    A + B Problem II
    Number Sequence
    Fibonacci Again
    8615 快乐
    8635 气球
    大牛之路II
    8617 阶乘数字和
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8549785.html
Copyright © 2011-2022 走看看