BZOJ2004: [Hnoi2010]Bus 公交線路
阿新 • • 發佈:2017-09-25
fin scu 開始 復雜度 mes long long [1] gree ble
Submit: 747 Solved: 512
[Submit][Status][Discuss]
僅一行包含三個正整數N K P,分別表示公交車站數,公交車數,相鄰站臺的距離限制。
N<=10^9,1<P<=10,K<N,1<K<=P
樣例二:5 2 3
樣例三:10 2 4
3
81 P,K小得不行,想到了狀態壓縮。n的範圍如此之大,考慮矩陣快速冪!
先從簡單的狀態壓縮開始。設$dp[i][j]$為強制選第i號停車,從第i號開始的後面p個的停車狀態。轉移。
發現一個問題(1->3,2->4)和(2->4,1->3)屬於同一種情況,所以我們只需要考慮dp[i-1]->dp[i]。
關鍵就是後面狀態j的轉移關系了。發現dp[i-1][j‘]->dp[i][j]滿足j‘變成j時實際位置對應的狀態中的二進制數的位數+1
那麽先刪去i-1位置的數,j‘-=(1<<(p-1)),然後j‘<<1,變成對應的位置,由於j‘->j時只有一個相對位置發生了變化,那麽j‘^=j,判斷j‘的二進制數中1的個數是否為1即可。
那麽轉移方程就出來了。考慮構造矩陣。
暴力構造矩陣的話大小是(2^p)^2的顯然不行,我們只需考慮後面的p位中有k位有車的狀態,不妨先DFS找出所有的狀態,然後兩兩枚舉即可。註意轉移關系在矩陣中對應的位置
不難發現構造的矩陣大小是(C(p-1,k-1))的,那這個就很對了。
所以總的復雜度是O(logn*C(p-1,k-1)^3+p!)的。
}
2004: [Hnoi2010]Bus 公交線路
Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 747 Solved: 512
[Submit][Status][Discuss]
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
Output
僅包含一個整數,表示滿足要求的方案數對30031取模的結果。
Sample Input
樣例一:10 3 3樣例二:5 2 3
樣例三:10 2 4
Sample Output
13
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[i][j]$為強制選第i號停車,從第i號開始的後面p個的停車狀態。轉移。
發現一個問題(1->3,2->4)和(2->4,1->3)屬於同一種情況,所以我們只需要考慮dp[i-1]->dp[i]。
關鍵就是後面狀態j的轉移關系了。發現dp[i-1][j‘]->dp[i][j]滿足j‘變成j時實際位置對應的狀態中的二進制數的位數+1
那麽先刪去i-1位置的數,j‘-=(1<<(p-1)),然後j‘<<1,變成對應的位置,由於j‘->j時只有一個相對位置發生了變化,那麽j‘^=j,判斷j‘的二進制數中1的個數是否為1即可。
暴力構造矩陣的話大小是(2^p)^2的顯然不行,我們只需考慮後面的p位中有k位有車的狀態,不妨先DFS找出所有的狀態,然後兩兩枚舉即可。註意轉移關系在矩陣中對應的位置
不難發現構造的矩陣大小是(C(p-1,k-1))的,那這個就很對了。
所以總的復雜度是O(logn*C(p-1,k-1)^3+p!)的。
}
#include<bits/stdc++.h> #define ll long long #define RG register #define il inline #define N 200 #define mod 30031 using namespace std; int n,k,p,que[N]; struct matrix{ int n,m; ll ma[N][N]; void clear(){memset(ma,0,sizeof(ma));n=m=0;} matrix operator *(const matrix & a)const { matrix c;c.clear(); c.n=n,c.m=a.m; for(int i=1;i<=c.n;++i){ for(int j=1;j<=c.m;++j){ for(int k=1;k<=m;++k){ c.ma[i][j]+=ma[i][k]*a.ma[k][j]; } (c.ma[i][j]+=mod)%=mod; } } return c; } }; matrix qp(matrix a,ll b){ if(b==1)return a;if(b==2)return a*a; matrix tmp=qp(a,(b>>1)); tmp=tmp*tmp; if(b&1)tmp=tmp*a; return tmp; } void dfs(int pos,int num,int cnt){ if(cnt==k){que[++que[0]]=num;return;} for(int i=pos-1;i!=-1;i--) dfs(i,num+(1<<i),cnt+1); } #define lowbit(o) ( (o) & (-o) ) bool check(int x,int y){ int Temp=x-(1<<(p-1)); Temp<<=1;Temp^=y; if(Temp==lowbit(Temp))return 1; return 0; } int main(){ scanf("%d%d%d",&n,&k,&p); dfs(p-1,(1<<(p-1)),1); matrix temp;temp.clear();temp.n=temp.m=que[0]; matrix ans;ans.clear();ans.ma[1][1]=1;ans.n=que[0],ans.m=1; for(int i=1;i<=que[0];++i){ for(int j=1;j<=que[0];++j){ if(check(que[i],que[j]))temp.ma[j][i]=1; } } temp=qp(temp,n-k); ans=temp*ans; cout<<ans.ma[1][1]; return 0; }
BZOJ2004: [Hnoi2010]Bus 公交線路