狀壓+矩乘的好題。
因為每\(p\)個位置中,每輛車就至少有\(1\)個位置,
所以我們可以狀壓一下。
設\(f[i][j]\)表示:
區間\([i,i+p-1]\)內的車站現在的規劃情況是\(j\)的方案數。
顯然,必有\(j\)的第\(p\)位是\(1\),且\(j\)共有\(k\)位是\(1\)(\(j\)的第\(p\)位對應著\(i\))。
則\(f[i][j]=\sum f[i-1][k]\),其中\(k\)能轉移到\(j\)。
那什麼樣的\(k\)能轉移到\(j\)呢?
我們將\(k\)左移一位(即增加了 \(i+p-1\) 一位),然後刪去第\(p\)位的數(即刪去第 \(i-1\) 位),得到了乙個\(k'\)。
如果\(k'\)和\(j\)只相差恰好\(1\)位,那麼\(k\)就可以轉移到\(j\)(第\(i-1\)位的車剛好跑到了著相差的一位)。
然後發現,對於每個\(f[i][j]\),它的祖先的\(k\)都是完全一致的;因此可以矩乘優化,建立轉移矩陣\(t[k][j]\),如果狀態\(k\)可以轉移到\(j\),則\(t[k][j]=1\),否則為\(0\)。
則複雜度為\(s^3\log n\),其中\(s\)是合法狀態數量(即符合\(j\)的第\(p\)位是\(1\),且\(j\)共有\(k\)位是\(1\)的\(j\)的數量)。我們有\(s=c_^\),當\(p=10,k=5\ \operatorname\ 6\)時取得最大值,有\(s=c_9^4\ \operatorname\ c_9^5=126\)。
**:
#includeusing namespace std;
const int mod=30031;
int n,m,p,len,sta[150];
struct mat
friend mat operator *(const mat &x,const mat &y)
int main()
HNOI2010 公交線路
看到k,p的範圍這麼小,顯然要狀壓dp啊!但是要怎麼狀壓dp呢。我們先注意到每p個公交站,這k輛公交車都要至少出現一次。因為答案是按集合算的,所以公交車之間不做區別,換句話說就是我們可以講題目簡化一下 1 n的n個元素,k個集合,保證乙個元素只出現在乙個集合中 不能多餘乙個也不能少於乙個 任意乙個集...
HNOI2010 公交線路 bus
標籤 狀態壓縮 矩陣快速冪。題解 首先看範圍,p 10,那麼我們可以想到狀態壓縮。我們把從乙個長度為10的區間進行壓縮,1代表可以,那麼當值乙個區間的1的個數為k個,我們就認為他是合法的。要注意這裡所定義的區間,是有起點的,但是沒有記下來,因為沒有必要。然後我們就可以想一下狀態是怎麼轉移的。那麼可行...
hnoi2010 彈飛綿羊
題目描述很明確,現在的目標是均攤兩個操作的複雜度 現在我們已知有兩種方法 1.每次用o 1 的時間修改k值,用o n 的時間直接模擬回答詢問 2.每次修改了k值後用o n 的時間更新所有答案,o 1 時間回答 均攤這兩種操作,可以這樣做 由於只可以從前往後跳,所以可以把跳躍路徑壓縮,更新時把壓縮的部...