题目描述 Description
小 Z 所在的城市有 N 个公交车站,排列在一条长为 N-1 公里的直线上,从左到右依次编号为1到 N,相邻公交车站间的距离均为 1公里。
作为公交车线路的规划者,小 Z调查了市民的需求,决定按以下规则设计线路:
1. 设共有K辆公交车,则 1到K 号车站作为始发站,N-K+1到 N号车站作为终点站。
2. 每个车站必须被一辆且仅一辆公交车经停(始发站和终点站也算被经停)。
3. 公交车只能从编号较小的车站驶向编号较大的车站。
4. 一辆公交车经停的相邻两个车站间的距离不得超过P 公里。
注意“经停”是指经过并停车,因经过不一定会停车,故经停与经过是两个不同的概念。
在最终确定线路之前,小 Z 想知道有多少种满足要求的方案。由于答案可能很大,你只需求出答案对30031取模的结果。
输入描述 Input Description
输入文件只有一行,其中包含用空格隔开的三个正整数N, K,
P,分别表示公交车站数,公交车数,一辆公交车经停的相邻两个车站间的最大距离。
输出描述 Output Description
仅包含一个整数,表示满足要求的方案数对30031取模的结果。
Sample Input
样例一:10 3 3
样例二:5 2 3
样例三:10 2 4
Sample Output
1
3
81
数据范围及提示 Data Size & Hint
输入的数据保证40%的数据满足N≤1000。100%的数据满足1
<
N<10^9,1
<
P≤10,K
<
N,1
<
K≤P
由于BZOJ题面又一次挂了…从Codevs沾来了题面.
看到题目发现N这么大,又是求路径方案数,很自然的想到HH去散步,也就是把原图变成矩阵然后做矩阵快速幂.
但是注意到题目里还有个P,P还只有10,那说不定是状压DP.
然后呢…
我们假设现在有一列公交车,事先规定转移时候先转移最靠前的公交车.
用2^p的二进制数表示状态,这个数的二进制位总共有k位为1,且为了满足之前的规定最高位必须为1.
然后就可以p个p个转移.
我们知道合法状态最多有C(9,4)=126种.
然后状压DP+矩乘快速幂.搞定.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define P 30031
#define MAXN 20
#define SIZE 200
#define LL long long
#define lowbit(x) (x&(-x))
using namespace std;
int n,k,p,Size;
int Pow[MAXN]={1};
int cons[SIZE];
struct Matrix
{
LL a[SIZE][SIZE];
Matrix()
{
memset(a,0,sizeof(a));
}
inline friend Matrix operator *(Matrix A,Matrix B)
{
Matrix ret;
for (int i=1;i<=Size;i++)
for (int j=1;j<=Size;j++)
{
for (int k=1;k<=Size;k++)
ret.a[i][j]+=A.a[i][k]*B.a[k][j];
ret.a[i][j]%=P;
}
return ret;
}
inline friend Matrix operator ^(Matrix x,int N)
{
Matrix ret;
for (int i=1;i<=Size;i++) ret.a[i][i]=1;
for (int i=N;i;i>>=1,x=x*x)
if (i&1) ret=ret*x;
return ret;
}
}ans,_a,_b;
void init(int x,int num,int sum)
{
if (num==k)
{
cons[++Size]=sum;
return;
}
for (int i=x-1;i;i--) init(i,num+1,sum+Pow[i-1]);
}
void pre()
{
for (int i=1;i<=Size;i++)
for (int j=1;j<=Size;j++)
{
int x=((cons[i]<<1)^Pow[p])^cons[j];
if (x==lowbit(x)) _b.a[i][j]=1;
}
}
int main()
{
scanf("%d%d%d",&n,&k,&p);
for (int i=1;i<=p;i++) Pow[i]=Pow[i-1]<<1;
init(p,1,Pow[p-1]);pre();ans.a[1][1]=1;
_a=_b^(n-k);ans=ans*_a;
cout<<ans.a[1][1]<<endl;
}