bzoj 2004[Hnoi2010]Bus 公交线路
状压DP。
f[i][s]表示第i个车站之前的p位的状态为s的方案数,注意这里状态s我们规定第一位为1,并且一共有k个1。
这样的话状态一共有C(9,4)=126种,于是设计一个126*126的矩阵,自乘n-m次就可以了;
初始状态:11111(m个1)的状态;
目标状态:11111(m个1)的状态。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 1200 7 #define inf 2147483647 8 #define ms 30031 9 using namespace std; 10 int st[maxn],v[maxn]; 11 int n,m,p,num,ans; 12 struct mat 13 { 14 int m[200][200]; 15 void clean() 16 { 17 for (int i=1;i<=num;i++) 18 for (int j=1;j<=num;j++) 19 m[i][j]=0; 20 } 21 friend mat operator *(const mat &a,const mat &b) 22 { 23 mat c; 24 c.clean(); 25 for (int i=1;i<=num;i++) 26 for (int j=1;j<=num;j++) 27 { 28 for (int k=1;k<=num;k++) 29 c.m[i][j]=c.m[i][j]+(a.m[i][k]*b.m[k][j])%ms; 30 c.m[i][j]=c.m[i][j]%ms; 31 } 32 return c; 33 } 34 }T,E; 35 36 bool judge(int x) 37 { 38 if (x%2==0) return 0; 39 int cnt=0; 40 for (int i=1;i<=p;i++) 41 { 42 if (x&1) cnt++; 43 x=x/2; 44 } 45 if (cnt!=m) return 0; 46 else return 1; 47 } 48 49 void debug(mat *a) 50 { 51 for (int i=1;i<=num;i++) 52 { 53 for (int j=1;j<=num;j++) 54 cout<<a->m[i][j]<<' '; 55 cout<<endl; 56 } 57 } 58 59 int main() 60 { 61 scanf("%d%d%d",&n,&m,&p); 62 for (int i=1;i<=((1<<p)-1);i++) 63 if (judge(i)) st[++num]=i,v[i]=num; 64 for (int i=1;i<=num;i++) 65 { 66 int x=st[i]; 67 int y=x/2; 68 for (int j=1;j<=p;j++) 69 if (v[y|(1<<(j-1))]) T.m[i][v[y|(1<<(j-1))]]=1; 70 } 71 //debug(&T); 72 E.m[1][v[(1<<m)-1]]=1; 73 int tmp=n-m; 74 while (tmp) 75 { 76 if (tmp&1) E=E*T; 77 tmp=tmp>>1; 78 T=T*T; 79 } 80 ans=E.m[1][v[(1<<m)-1]]; 81 printf("%d\n",ans); 82 return 0; 83 }
AC without art, no better than WA !