花園 洛谷 1357 狀壓DP 矩陣虧快速冪

2021-08-10 01:54:44 字數 1673 閱讀 5747

題目描述

小l有一座環形花園,沿花園的順時針方向,他把各個花圃編號為1~n(2<=n<=10^15)。他的環形花園每天都會換乙個新花樣,但他的花園都不外乎乙個規則,任意相鄰m(2<=m<=5,m<=n)個花圃中有不超過k(1<=k

例如,n=10,m=5,k=3。則

ccpcppppcc 是一種不符合規則的花圃;

ccppppcpcp 是一種符合規則的花圃。

請幫小l求出符合規則的花園種數mod 1000000007

由於請您編寫乙個程式解決此題。

輸入輸出格式

輸入格式:

一行,三個數n,m,k。

輸出格式:

花園種數mod 1000000007

輸入輸出樣例

輸入樣例#1: 複製

【樣例輸入1】

10 5 3

【樣例輸入2】

6 2 1

輸出樣例#1: 複製

【樣例輸出1】

458【樣例輸出2】

18說明

【資料規模】

40%的資料中,n<=20;

60%的資料中,m=2;

80%的資料中,n<=10^5。

100%的資料中,n<=10^15。

分析:額,本來想刷數學題的,結果被這道題撞車了,實在好久沒寫過矩陣快速冪,於是各種qiao。首先80%不難想到狀壓dp,因為m小於5嘛,然後定義轉移方程f[i]

[j],表示拿到第i個花時,後m個花的狀態是j的方案數,現在考慮哪些狀態可以轉移,不難看出j狀態可以由j>>2+1,j>>2+2^(m-1)+1(手動模擬一下吧),這兩個狀態轉移過來於是打上標記con[i]

[j],於是可以寫出乙個n*2^(m-1)*

2^(m-1)的轉移方程,f[i]

[j]=f[

i-1][k

]+f[i]

[j]。這是80分的做法,現在n太大於是考慮優化,我們觀察一下可以發現,後面的每種方案數其實就是前面的方案遞推過去的,遞推規則是不變的,且推了n次,然後手動玩了下樣例,發現最後的方案數就等於最開始處理出來的con[i]

[j]的n次方,於是考慮矩陣快速冪(很裸的)。最後也是最玄學的地方,你可以玩個樣例觀察一下,發現答案就是矩陣的對角線和,至於為什麼,可以這樣考慮,我們最後算出的結果肯定是sigma(f[

n+m][i

]),而對角線上的點的值其實就對應每種狀態i,於是考慮把它們加起來得到最優解。最後說一下,取模一定要勤快。

# include # include # include # include # include # include # include # include using namespace std;

typedef long long ll;

ll read()

while(ch>='0'&&ch<='9')

return f*i;

}const int mod=1000000007;

ll con[40][40],res[40][40],n,m,k,tmp[40][40];

bool vis[40];

inline void mul(ll s[40],ll t[40])

}int main()

if(sum<=k)

res[i][i]=1;

} kum();ll ans=0;

for(int i=0;i<(1<

狀壓dp 矩陣 洛谷 P1357 花園

簡單來說,這一題就是乙個狀壓dp用矩陣優化 但是這個矩陣也是最最最基礎的矩陣了 floyd矩陣 dp的話,和第乙個題解hi一樣的 f i s 表示第i位時的方案,s為i i m 1的狀態 然後轉移的時候我們列舉i列舉2個s if v j k f i j f i j f i 1 k mo 這裡的v j...

洛谷 1357 花園

的運算優先順序低於 貌似對矩陣理解更深刻了!2 m 5,相鄰的m個花圃可能有2 m種狀態 用0 2 m 1來表示 要求有不超過k個c形花圃,對應其二進位制形式中的0不超過k個。標記出0 2 m 1中滿足條件的狀態x,對於每個狀態x,前m個花圃會出現1次 f i,x 表示前i個花圃中,最後m個花圃的狀...

洛谷 1357 花園

的運算優先順序低於 貌似對矩陣理解更深刻了!2 m 5,相鄰的m個花圃可能有2 m種狀態 用0 2 m 1來表示 要求有不超過k個c形花圃,對應其二進位制形式中的0不超過k個。標記出0 2 m 1中滿足條件的狀態x,對於每個狀態x,前m個花圃會出現1次 f i,x 表示前i個花圃中,最後m個花圃的狀...