【BZOJ 2004】: [Hnoi2010]Bus 公交线路
题目链接:
题解:
所以说,超显眼的数据范围啊。
很显然我们对于每个P的区间都是要有k个站被bus停留,然后考虑转移的话应该是把这k个站里的某个bus往前走,那么转移也很显然了,n的范围很大,所以直接上矩阵。
代码:
#define Troy #include <bits/stdc++.h> using namespace std; inline int read(){ int s=0,k=1;char ch=getchar(); while(ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar(); while(ch>47&ch<='9') s=s*10+(ch^48),ch=getchar(); return s*k; } const int N=129,mod=30031; int n,k,p,BGM,stk[N],m; struct Matrix{ int a[N][N]; Matrix(){memset(a,0,sizeof(a));} inline void evoid(){ for(int i=0;i^m;++i) a[i][i]=1; } inline friend Matrix operator *(const Matrix &x,const Matrix &y){ Matrix c; for(int i=0;i^m;++i) for(int j=0;j^m;++j) for(int k=0;k^m;++k) c.a[i][j]=(c.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod; return c; } inline friend Matrix operator ^(Matrix x,int b){ Matrix ret;ret.evoid(); while(b){ if(b&1)ret=ret*x; b>>=1;x=x*x; }return ret; } }; inline bool move_to(int to,int from){ from^=1<<p-1; from<<=1; int deta=from^to; return (deta&(-deta))==deta; } int main(){ n=read(),k=read(),p=read(); register int i,j; for(i=(1<<p-1);i^(1<<p);++i){ int x=i; for(j=0;x;x^=(x&(-x)),++j); if(j==k){ if(i==(1<<p)-(1<<p-k)) BGM=m; stk[m++]=i; } } Matrix ans,t; ans.a[BGM][0]=1; for(i=0;i^m;++i) for(j=0;j^m;++j){ t.a[i][j]=move_to(stk[j],stk[i]); } ans=(t^(n-k))*ans; printf("%d\n",ans.a[BGM][0]); }
没有什么不可能。