JSOI2017 奧術 (遞推)

2022-05-01 04:57:11 字數 1235 閱讀 6943

很巧妙的遞推題。

設\(cnt[i]\)表示字尾\(i\)有多個字首可以變成空。

若能求出最小的\(j\),滿足\(s[i..j]\)會變成空,那麼\(cnt[i]=cnt[j]+1\)

同理,可以設出狀態\(f[i][c]\)表示要\(s[i..f[i][c]-1]\)變成\(c\),\(f[i][c]\)最小是多少。

倒著列舉\(i\),\(f\)有初值\(f[i][s[i]]=i+1\)

然後從小到大列舉字元\(c\),假設已經求出了\(f[i][c]\)

若有一條限制\((x,y,z)\)的\(x=c\),那麼就有一種走法\(f[i][z]=f[f[i][x]][y]\)

取所有走法的\(f[f[i][x]][y]\)的最小值,那麼這就是下一步走到的地方。

注意還有一種轉移是\(f[i][c]=f[f[i][*]][c]\)

所以先做一次求出\(f[i][*]\),再做一次用\(f[i][*]\)去更新\(f[i][c]\)。

code:

#include#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)

#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)

#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)

#define ll long long

#define pp printf

#define hh pp("\n")

using namespace std;

const int n = 2e5 + 5;

char s[n], str[10];

int n, len, a[n][3];

const int inf = 1e9;

int f[n][27];

ll cnt[n];

int main()

} fo(i, 1, len + 1)

fd(i, len, 1)

} fo(j, 0, 25)

} if(f[i][26] < inf) cnt[i] = cnt[f[i][26]] + 1;

} ll ans = 0;

fo(i, 1, len) ans += cnt[i];

pp("%lld\n", ans);

}

物件導向部分 201

小夥伴們,還在為不知道怎麼下手而頭疼嗎,我們程式競賽協會來幫你們啦 啦啦啦。另外,如果有對程式設計含有濃厚興趣的同學,我們隨時歡迎你們的加入喲 策劃 譚兆飛 程式設計 管懷文 協助 一號人員要求給她打碼 乾脆二號也打碼好了o o 其實只是提供了題目啦 物件導向部分 201 include inclu...

2 01揹包問題

有 nn 件物品和乙個容量是 vv 的揹包。每件物品只能使用一次。第 ii 件物品的體積是 vivi,價值是 wiwi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,vn,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n...

2 01揹包問題

有 nn 件物品和乙個容量是 vv 的揹包。每件物品只能使用一次。第 ii 件物品的體積是 vivi,價值是 wiwi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。第一行兩個整數,n,vn,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 nn 行,每...