BZOJ 1090 字串摺疊 區間DP

2022-05-27 01:03:12 字數 1829 閱讀 4957

很明顯的區間dp,設dp[l][r]表示[l,r]區間的字串摺疊後的最小長度。

可以通過兩種方向轉移,dp[l][r]=min(dp[l][i]+dp[i+1][r]).

另一種是摺疊,dp[l][r]=min(dp[l][l+k-1]+cal((r-l+1)/k)+2).其中k是能整除(r-l+1)的數且區間能夠摺疊成k份,cal()函式計算數字的位數。

另外用了線段樹維護hash值,可以每次驗證logn。

# include # include 

# include

# include

# include

# include

# include

# include

# include

# include

# include

using

namespace

std;

# define lowbit(x) ((x)&(-x))

# define pi acos(-1.0

)# define eps 1e-8

# define mod

1000000007

# define inf

1000000000

# define mem(a,b) memset(a,b,

sizeof

(a))

# define for(i,a,n)

for(int i=a; i<=n; ++i)

# define fo(i,a,n)

for(int i=a; ii)

# define bug puts("h

");# define lch p

<<1

,l,mid

# define rch p

<<1|1,mid+1

,r# define mp make_pair

# define pb push_back

typedef pair

pii;

typedef vector

vi;# pragma comment(linker,

"/stack:1024000000,1024000000")

typedef

long

long

ll;int

scan()

void out(int

a)

if(a>=10) out(a/10

); putchar(a%10+'0'

);}const

int n=105;//

code begin...

char

s[n];

intdp[n][n], n;

ll seg[n

<<2

], power[n];

void push_up(int p, int l)

void init(int p, int l, int

r) seg[p]=s[l];

}ll query(

int p, int l, int r, int l, int

r)int qiu(int

x)int cal(int l, int r, int

k)

if (!flag) return

inf;

else

return dp[l][l+k-1]+qiu((r-l+1)/k)+2;}

int dfs(int l, int

r)int

main ()

view code

bzoj1090 字串摺疊

問題描述 摺疊的定義如下 1.乙個字串可以看成它自身的摺疊。記作s s 2.x s 是x x 1 個s連線在一起的串的摺疊。記作x s ssss s x個s 3.如果a a b b 則ab a b 例如,因為3 a aaa,2 b bb,所以3 a c2 b aaacbb,而2 3 a c 2 b ...

bzoj1090(區間dp,字串摺疊問題)

這個問題比上乙個簡單一點,應該對比一下兩題的相似與不同點,來找到解題的技巧 這題是用遞推實現的,不用記憶化。f l r 表示,把l r這個區間摺疊的最短長度,然後我們想,對於乙個區間來說,我們有兩種選擇,一種是把這個區間它自己來摺疊,另一種是兩塊已經摺疊的區間接起來。對於第二中情況,直接列舉斷點 兩...

1090 SCOI2003 字串摺疊

題目鏈結 題目大意 摺疊的定義如下 1.乙個字串可以看成它自身的摺疊。2.x s 是x x 1 個s連線在一起的串的摺疊,記作x s 3.摺疊可以巢狀。給乙個字串,求它的最短摺疊。題解 區間dp f l r 表示 l r 壓縮後最短長度,初始值f l r r l 1 轉移 列舉區間分割點k,l k ...