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
样例二:5 2 3
样例三:10 2 4
Sample Output
1
3
81
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
正解:状压$dp$+矩阵快速幂优化。
以前考过,当时什么都不会,现在看来还是不难吧。。
不过一直在想矩阵快速幂会$T$啊,结果就被告知状态数其实很少,可以把它离散化(差不多这意思吧)。。
所以大概就是设$f[i][j]$表示到了第$i$个站,所有公交车离这个车站的距离的状态为$j$,这个转移是暴力的。
乍一看,$j$可以取$[0,2^{p}-1]$这么多状态,但是我们可以发现,每次都有一个公交车与这个车站的距离为$0$,所以我们状态数可以$/2$。
然后我们又可以发现,$j$里面一定有$k-1$个$1$,那么我们算一下$inom{p-1}{k-1}$,发现最大只有$inom{9}{4}=126$。
于是我们把这些状态压到一个数组里,如果$i$状态可以转移到$j$状态,那么转移矩阵的$[i][j]$这个位置就可以赋为$1$。
那么初始状态是$f[k][2^{p}-2]=1$,乘上转移矩阵的$n-k$次方,找到$f[n][2^{p}-2]$就是答案了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define rhl (30031) 6 7 using namespace std; 8 9 struct data{ int m[130][130]; }a,b; 10 11 int st[130],n,k,p,sz,now; 12 13 il int gi(){ 14 RG int x=0,q=1; RG char ch=getchar(); 15 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 16 if (ch=='-') q=-1,ch=getchar(); 17 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 18 return q*x; 19 } 20 21 il int calc(RG int s){ 22 RG int res=0; while (s) res+=s&1,s>>=1; return res; 23 } 24 25 il int can(RG int i,RG int j){ 26 RG int x; 27 if (st[i]>>(p-1)&1){ 28 x=(st[i]^(1<<(p-1)))<<1; 29 return (x|2)==st[j]; 30 } 31 if ((st[i]<<1)==st[j]) return 1; 32 for (RG int s=0;s<p;++s) 33 if (st[i]>>s&1){ 34 x=(st[i]^(1<<s))<<1; 35 if ((x|2)==st[j]) return 1; 36 } 37 return 0; 38 } 39 40 il data mul(data a,data b){ 41 data c; 42 for (RG int i=1;i<=sz;++i) 43 for (RG int j=1;j<=sz;++j){ 44 c.m[i][j]=0; 45 for (RG int k=1;k<=sz;++k) 46 (c.m[i][j]+=a.m[i][k]*b.m[k][j])%=rhl; 47 } 48 return c; 49 } 50 51 il data qpow(data a,RG int b){ 52 data ans=a; --b; 53 while (b){ 54 if (b&1) ans=mul(ans,a); 55 a=mul(a,a),b>>=1; 56 } 57 return ans; 58 } 59 60 int main(){ 61 #ifndef ONLINE_JUDGE 62 freopen("bus.in","r",stdin); 63 freopen("bus.out","w",stdout); 64 #endif 65 cin>>n>>k>>p; 66 for (RG int s=0;s<(1<<p);++s) 67 if (!(s&1) && calc(s)==k-1) st[++sz]=s; 68 for (RG int i=1;i<=sz;++i) 69 for (RG int j=1;j<=sz;++j) 70 if (can(i,j)) b.m[i][j]=1; 71 for (RG int i=1;i<=sz;++i) 72 if (st[i]+1==(1<<k)-1) a.m[1][now=i]=1; 73 b=qpow(b,n-k),a=mul(a,b); 74 cout<<a.m[1][now]; return 0; 75 }