petya遇到了乙個關於括號序列的問題:
給定乙個字串s,它代表著正確的括號序列,即(「(」)與 (「)」)是匹配的。例如:「(())()」 和 「()」是正確的,「)()」與「(()」則不是正確的。
在正確的括號序列中,乙個左邊的括號一定是匹配乙個右邊的括號(反之亦然)。例如,在下圖中,第 3 個括號匹配第 6 個括號,第 4 個括號匹配第 5 個括號。
現在你需要對乙個正確的括號序列做塗色操作,嚴格滿足以下三個條件:
每個括號要麼不塗色,要麼塗紅色,要麼塗藍色。
一對匹配的括號需要且只能將其中乙個塗色。
相鄰的括號不能塗上同一種顏色(但是可以都不塗顏色)。
求:給整個括號序列塗上顏色的方案數,答案可能比較大,對 1e9
+71e9+7
1e9+
7 取模。
用dp[x][y][i][j]
表示 x
xx 到 y
yy 這個區間左端點染 i
ii,右端點染 j
jj 的方案數。首先用棧預處理出每個左端點對應的右端點,然後轉移的時候考慮三種情況:
區間長度為 2
22,這時候列舉 4
44 種染色情況,每種方案都是 111。
match[x]==y
時,先處理 x−1
x-1x−
1 到 y−1
y-1y−
1,再根據邊界的染色情況進行轉移。
match[x]!=y
時,先分別處理 x
xx 到match[x]
和match[x]+1
到 y
yy,再根據邊界的染色情況進行轉移。
每次遞迴處理的子區間都是合法的括號序列。
#include
#include
#include
#include
using
namespace std;
#define ll long long
const
int maxn=
705;
char s[maxn]
;ll dp[maxn]
[maxn][3
][3]
;//dp[i][j][k][h]表示區間i~j左右端點顏色分別為k,h的情況數
const
int mod=
1e9+7;
int match[maxn]
;//用來儲存互相匹配的括號 match[i]表示與i匹配的括號
void
get(
int l)
else}}
void
**dp
(int a,
int b)
if(match[a]
==b)
if(i!=1)
if(j!=2)
if(i!=2)
}}return;}
//不為匹配的
int t=match[a]
;//從與當前括號匹配那個的開始分割
**dp
(a,t)
;**dp
(t+1
,b);
for(
int i=
0;i<
3;i++)}
}}}}
intmain()
}printf
("%lld"
,ans)
;return0;
}
樹上染色題解
有一棵點數為n的樹,樹邊有邊權。將m個點染成黑色,並將其他的點染成白色。會獲得黑點兩兩之間的距離和加上白點兩兩之間的距離和的收益。問收益最大值是多少。輸入格式 第一行兩個整數n m。接下來n 1行,每行三個整數a b c,表示有一條樹邊連線a b,長度為c。輸出格式 一行 乙個正整數,表示收益的最大...
SDOI2011 染色 題解
題目大意 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 思路 樹剖之後,維護其兩端的顏色 答案和標記即可。include include define n 100001 using...
題解 括號匹配
題解 描述假設表示式中只包含三種括號 圓括號 方括號和花括號,它們可相互巢狀,如 或 等均為正確的格式,而 或均為不正確的格式.輸入一串括號 如果輸入的右括號多餘,輸出 extra right brackets 如果輸入的左括號多餘,輸出 extra left brackets 如果輸入的括號不匹配...