[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\n",ans.a[1][w[x]]);
74 }

 

posted @ 2018-03-12 16:03  Z-Y-Y-S  阅读(280)  评论(0编辑  收藏  举报