# P41.99 million Path to Trail Solution

Luogu Portal

## Solution

Good name.

A lazy dog like me must be looking directly at the simplified title!

The Title lets us find the number of discontinuous palindrome sub-sequences. We find that it is not very good, so we change our thinking to ask:

$Number of Palindrome Subsequences (Continuable) - Number of Palindrome Substrings$

It is easy to find the number of palindrome substrings, that is, the $$manacher$$ board. Let's consider how to find the number of palindrome substrings.

Set point $$id$$ to be the symmetric center of a subsequence. If $$S_{i-j} = S_{i + j}$$, our answer will have one more choice. Assuming there are $$i$$ choices for the symmetric center $$f_i = x$$, then:

1. $$i$$ is a character, and the answer is $$2^{x + 1} - 1$$. There are $$x + 1$$ selected or unselected characters, including the symmetric center, so there are $$x + 1$$ cases in common $$2^{x + 1}$$, and one case minus the empty set is the answer.
2. $$i$$ In the middle of two characters, the answer is $$2^x-1$$, that is, the symmetric center cannot be included.

From the discussion above, you can see that the symmetric center is between two characters, so we doubled the original string as $$manacher$$, so the center must be the whole point.

So how do I find this $$f_i$$?

Construct the generation function:

$F(x) = \sum\limits_{i = 0}^{|s| - 1}a_ix^i$

Then let $$F(x)$$ roll itself up, that is, $$F(x)^2$$, either NTT or FFT.

It is not difficult to find that the coefficient of $$x^i$$ in (F(x)^2\) is the number of symmetrical character pairs $$\frac{i}{2}$$ in the original string.

It is also observed that only a and b are in the input string, and there is no correlation between the two characters, so consider them separately:

1. For a, if \ (S_i = a\), then \ (A_i = 1\) and vice versa \ (A_i = 0\).
2. For the same reason for b, if \ (S_i = b\), then \ (B_i = 1\) and vice versa \ (B_i = 0\).

We can calculate $$f_i) after we have worked out \(A) and \(B$$.

$f_i = A^2 + B^2$

## Code

The NTT I'm using here requires two modules. Be careful not to mix up QwQ when writing

#include <bits/stdc++.h>
#define ll long long
#define cl const ll

using namespace std;

namespace IO{
ll x = 0;
char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}

template <typename T> inline void write(T x){
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;

const ll N = 3e5 + 10;
const ll mod = 998244353, Mod = 1e9 + 7;
const ll G = 3, Gi = 332748118;
ll n, m, ans1, ans2;
ll a[N], b[N], c[N], d[N], rev[N];
int p[N];
char s[N], t[N];

namespace NTT{
ll lim, len;

inline ll qpow(ll a, ll b, ll mod){
ll res = 1;
while(b){
if(b & 1) res = res * a % mod;
a = a * a % mod, b >>= 1;
}
return res;
}

inline void get_rev(cl n){
lim = 1, len = 0;
while(lim < n) lim <<= 1, ++len;
for(int i = 0; i < lim; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1));
}

inline void ntt(ll A[], cl lim, cl type){
for(int i = 0; i < lim; ++i)
if(i < rev[i]) swap(A[i], A[rev[i]]);
for(int mid = 1; mid < lim; mid <<= 1){
ll Wn = qpow(type == 1 ? G : Gi, (mod - 1) / (mid << 1), mod);
for(int i = 0; i < lim; i += (mid << 1)){
ll w = 1;
for(int j = 0; j < mid; ++j, w = w * Wn % mod){
ll x = A[i + j], y = w * A[i + j + mid] % mod;
A[i + j] = (x + y) % mod;
A[i + j + mid] = (x - y + mod) % mod;
}
}
}
if(type == 1) return;
ll inv = qpow(lim, mod - 2, mod);
for(int i = 0; i < lim; ++i) A[i] = A[i] * inv % mod;
}

inline void Mul(cl n, cl m, ll a[], ll b[]){
get_rev(n + m);
ntt(a, lim, 1), ntt(b, lim, 1);
for(int i = 0; i < lim; ++i) a[i] = a[i] * b[i] % mod;
ntt(a, lim, -1);
}
}
using namespace NTT;

inline void manacher(){
n = strlen(t + 1);
s = '#', s[(n << 1) + 1] = '*';
for(int i = 1; i <= n; ++i)
s[(i << 1) - 1] = '*', s[i << 1] = t[i];
m = (n << 1) + 1;
int mx = 0, id = 0;
for(int i = 1; i <= m; ++i){
if(i < mx) p[i] = min(mx - i, p[(id << 1) - i]);
else p[i] = 1;
while(i - p[i] >= 1 && i + p[i] <= m && s[i - p[i]] == s[i + p[i]]) ++p[i];
if(i + p[i] > mx) id = i, mx = i + p[i];
}
for(int i = 1; i <= (n << 1) + 1; ++i) ans1 = (ans1 + (p[i] >> 1)) % Mod;
}

inline void solve(){
for(int i = 1; i <= n; ++i){
if(t[i] == 'a') a[i - 1] = c[i - 1] = 1;
else b[i - 1] = d[i - 1] = 1;
}
Mul(n, n, a, c), Mul(n, n, b, d);
for(int i = 0; i <= (n << 1); ++i) c[i] = (a[i] + b[i]) % mod;
for(int i = 0; i <= (n << 1) - 2; ++i){
if(i & 1) ans2 = (ans2 + qpow(2, (c[i] >> 1), Mod) - 1 + Mod) % Mod;
else ans2 = (ans2 + qpow(2, (c[i] >> 1) + 1, Mod) - 1 + Mod) % Mod;
}
write((ans2 - ans1 + Mod) % Mod), puts("");
}

int main(){
scanf("%s", t + 1);
manacher();
solve();
return 0;
}


$\_EOF\_$

Posted on Wed, 01 Dec 2021 14:49:10 -0500 by pesoto74