Bzoj3160:万径人踪灭
2018-02-12 22:29
429 查看
题面
BzojSol
求不连续回文子序列的个数\(ans=\)回文子序列个数-连续回文子序列个数
即回文子序列个数-回文子串个数
后面直接\(Manacher\)就好了
考虑前面的
枚举对称轴,设\(f[i]\)表示对称轴\(i\)两边相同字符的对数
那么最终答案就是\(\sum 2^{f[i]}-1\)
考虑求\(f[i]\)
只有当原串中的两个字符相同才会有贡献
也就是\(s[i-x]=s[i+x]\)
单独考虑\(a\)和\(b\)的贡献
\(f[i]=\sum [s[i-x]==s[i+x]]\)
设当前考虑\(a\)的贡献
把是\(a\)的设为\(1\)不是的为\(0\),做个卷积就可以求出\(f\)
那么就可以\(FFT\)辣
注意两个字符之间也算对称轴
# include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int Zsy(1e9 + 7); const int _(5e5 + 5); const double PI(acos(-1)); int n, p[_]; ll f[_]; int N, M, l, r[_]; char s[_], a[_]; struct Complex{ double real, image; IL Complex(){ real = image = 0; } IL Complex(RG double a, RG double b){ real = a, image = b; } IL Complex operator +(RG Complex B){ return Complex(real + B.real, image + B.image); } IL Complex operator -(RG Complex B){ return Complex(real - B.real, image - B.image); } IL Complex operator *(RG Complex B){ return Complex(real * B.real - image * B.image, real * B.image + image * B.real); } } A[_], B[_]; IL void FFT(RG Complex *P, RG int opt){ for(RG int i = 0; i < N; ++i) if(i < r[i]) swap(P[i], P[r[i]]); for(RG int i = 1; i < N; i <<= 1){ RG Complex W(cos(PI / i), opt * sin(PI / i)); for(RG int j = 0, p = i << 1; j < N; j += p){ RG Complex w(1, 0); for(RG int k = 0; k < i; ++k, w = w * W){ RG Complex X = P[k + j], Y = w * P[k + j + i]; P[k + j] = X + Y, P[k + j + i] = X - Y; } } } } IL void Mul(){ FFT(A, 1); for(RG int i = 0; i < N; ++i) B[i] = A[i] * A[i]; FFT(B, -1); for(RG int i = 0; i < N; ++i) B[i].real = B[i].real / N + 0.5; for(RG int i = 1; i <= M; ++i) f[i] += ((ll)(B[i].real) + 1) >> 1; } IL ll Manacher(){ RG ll ans = 0; RG int mx = 0, len = 1; a[1] = '#'; for(RG int i = 1; i <= n; ++i) a[++len] = s[i], a[++len] = '#'; for(RG int i = 1, id = 0, mx = 0; i <= len; ++i){ if(i < mx) p[i] = min(mx - i, p[(id << 1) - i]); while(i - p[i] && i + p[i] <= len && a[i - p[i]] == a[i + p[i]]) ++p[i]; if(p[i] + i > mx) mx = p[i] + i, id = i; (ans += p[i] >> 1) %= Zsy; } return ans; } IL ll Pow(RG ll x, RG ll y){ RG ll ret = 1; for(; y; y >>= 1, x = x * x % Zsy) if(y & 1) ret = ret * x % Zsy; return ret; } int main(RG int argc, RG char* argv[]){ scanf(" %s", s + 1); n = strlen(s + 1); for(M = n + n, N = 1; N <= M; N <<= 1) ++l; for(RG int i = 0; i < N; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1)); RG ll ans = -Manacher(); for(RG int i = 0; i < N; ++i) A[i] = Complex(s[i] == 'a', 0); Mul(); for(RG int i = 0; i < N; ++i) A[i] = Complex(s[i] == 'b', 0); Mul(); for(RG int i = 1; i <= M; ++i) (ans += Pow(2, f[i]) - 1) % Zsy; printf("%lld\n", (ans + Zsy) % Zsy); return 0; }
相关文章推荐
- [BZOJ3160]万径人踪灭(FFT+Manacher)
- BZOJ3160:万径人踪灭 (FFT+Manacher)
- BZOJ[3160]万径人踪灭 FFT+Manacher
- bzoj 3160: 万径人踪灭 manachar+快速傅里叶变换
- 【BZOJ3160】万径人踪灭
- BZOJ 3160 万径人踪灭
- 【BZOJ 3160】 3160: 万径人踪灭 (FFT)
- [BZOJ3160]万径人踪灭(FFT+manacher)
- 【BZOJ3160】万径人踪灭 FFT manacher
- BZOJ3160 万径人踪灭(FFT+manacher)
- 【BZOJ3160】万径人踪灭
- [BZOJ3160]万径人踪灭 FFT+manacher
- BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher
- Bzoj3160:万径人踪灭
- [bzoj3160][FFT][manacher]万径人踪灭
- BZOJ3160:万径人踪灭 (manacher+FFT)(占位)
- BZOJ 3160 万径人踪灭
- BZOJ3160 万径人踪灭 FFT+manacher
- bzoj 3160: 万径人踪灭 manachar + FFT
- [BZOJ 3160]万径人踪灭(FFT+Manacher)