bzoj 3160 萬徑人蹤滅 FFT

2022-05-12 10:18:38 字數 1351 閱讀 3870

題目:

求出關於乙個位置有多少對對稱字母,如果 i 位置有 f[i] 對,對答案的貢獻是 2^f[i] - 1;

然後減去連續的,用 manachar 求出回文長度,每個位置作為邊界都是一種不合法情況;

求對稱,首先把字串中間穿插字元 '$',於是字串的長度變成2倍;

考慮一對字母 s[x],s[y],如果 s[x] = s[y],其對稱中心是 (x+y)/2;

放在加入字元後的字串中,對稱中心就是 x+y;

所以可以看出卷積了:f[i] = ∑(0<=j<=i) (s[j]==s[i-j]),其中 i 視為新字串中的位置,j 和 i-j 視為原字串中的位置;

注意卷積和 manachar 算的個數都要包括自己成對,否則判斷挺麻煩...

這裡卷積的兩個多項式其實是一樣的,所以只要用 fft 算出乙個,然後自己乘起來即可;

做下一步的時候注意清空,別忘了清空 n~lim 部分的值;

處理 bin 的邊界是 n 而非 n-1,因為最多可能有 n 對。

(學習了 manachar 的簡潔寫法)

**如下:

#include#include

#include

#include

#include

using

namespace

std;

typedef

double

db;int

const xn=(1

<<19),mod=1e9+7

;db

const pi=acos(-1.0

);int n,rev[xn],lim=1

,l,len[xn],bin[xn],c[xn];

char

ch[xn];

struct

coma[xn],b[xn],aa[xn];

com

operator + (com a,com b);}

com

operator - (com a,com b);}

com

operator * (com a,com b);}

int upt(int x)

void fft(com *a,int

tp);

for(int j=0,len=(mid<<1);jlen)

;for(int k=0;kwn)}}

}void

solve()

char

s[xn];

int manachar()//

+i self

return

ret;

}int

main()

BZOJ3160 萬徑人蹤滅

對於每個可以作為對稱軸的位置,我們算出以其為對稱軸有多少對位置和字元是對稱的,設為t i 若不考慮不能連續,則我們可以從這t i 對里任選出來任意對,都是可行的答案,且不重不漏,所以不考慮不能連續的情況的答案為sigma 2 t i 1,考慮不能是連續子串,再減去回文子串的數量即可 回文子串數量ma...

BZOJ 3160 萬徑人蹤滅

給定乙個由 a 和 b 構成的字串,求不連續回文子串行的個數。正難則反我們考慮容斥。對於連續的回文字串顯然是一次馬拉車就可以很好的求出來的,那我們設f i 表示以i為中心的對稱字元對數量,顯然答案就是 2 n 1 12f i 1 那麼我們的問題就轉變成了怎麼求出f i 我們考慮當這個字元為a的時候做...

bzoj3160 萬徑人蹤滅

題目在上方鏈結 description input output sample input sample output hint source 2013湖北互測week1 首先將字串中間插入 把他們分隔開 題目要求求不連續的回文串的個數 那麼就用總數減去連續的即可 考慮連續的部分 直接用manach...