题解 P4199/BZOJ3160【万径人踪灭】

简化题面

给定只含有字符\(a\)\(b\)的字符串,求位置关于某根轴对称的不连续回文子序列数量

解题思路

显然答案=总数-不合法的方案数。

本题中不合法的方案数显然为连续的回文子序列,即回文子串。可以使用\(\mathcal{Manacher}\)直接来求。

考虑怎么求总数,即位置关于某根轴对称的回文子序列

对于回文子序列的最长长度为\(l\)的回文子序列,他会含有\(\lceil\frac l2\rceil\)个对称的字符对,我们考虑先求出相同的\(a\)的字符对的数量,若当前位置为\(a\)则为\(1\)构造生成函数,然后自己卷自己即为相同的答案,然后在对\(b\)做相同的事情就是回文子序列的最长长度。

然后考虑其中含有的\(\lceil\frac l2\rceil\)个字符集可以选或者不选,那么我们可以想到答案为

\[\sum_{i=0}^{\lceil\frac l2\rceil-1}\dbinom{\lceil\frac l2\rceil}{i} \]

即为\(2^{\lceil\frac l2\rceil}-1\)

最后求出来相减就是答案

\(\mathcal{Code}\)

// Author: Ame__
#include<bits/stdc++.h>
#include<stdint.h>
#define _ 0
#define AME__DEBUG
#define bomb exit(0)
#define LOG(FMT...) fprintf(stderr , FMT)
#define TOWA(FMT...) fprintf(stdout , FMT)
using namespace std;
/*Grievous Lady*/
    
typedef int32_t i32;
typedef int64_t i64;
typedef double qwq;
    
const int BUF_SIZE = 1 << 12;
char buf[BUF_SIZE] , *buf_s = buf , *buf_t = buf + 1;
    
#define PTR_NEXT() \
{ \
    buf_s ++; \
    if(buf_s == buf_t) \
    { \
        buf_s = buf; \
        buf_t = buf + fread(buf , 1 , BUF_SIZE , stdin); \
    } \
}
    
#define mians(_s_) \
{ \
    while(!isgraph(*buf_s)) PTR_NEXT();\
    char register *_ptr_ = (_s_); \
    while(isgraph(*buf_s) || *buf_s == '-') \
    { \
        *(_ptr_ ++) = *buf_s; \
        PTR_NEXT(); \
    } \
    (*_ptr_) = '\0'; \
}
    
template <typename _n_> void mian(_n_ & _x_){
    while(*buf_s != '-' && !isdigit(*buf_s)) PTR_NEXT();
    bool register _nega_ = false; if(*buf_s == '-'){ _nega_ = true; PTR_NEXT(); }
    _x_ = 0; while(isdigit(*buf_s)){ _x_ = _x_ * 10 + *buf_s - '0'; PTR_NEXT(); } if(_nega_) _x_ = -_x_;
}
    
const i32 mod = 1e9 + 7;
const i32 kato = 2e6 + 10;
const i32 Mod = 998244353;

template <typename _n_> bool cmax(_n_ &a , const _n_ &b){ return a < b ? a = b , 1 : 0; }
template <typename _n_> bool cmin(_n_ &a , const _n_ &b){ return a > b ? a = b , 1 : 0; }

i32 n , cnt , ans , len = 1;
i32 f[kato] , g[kato] , h[kato] , p[kato] , pia[kato];
char s[kato] , res[kato];

inline i32 quick_pow(i32 a , i32 b){
    i32 res = 1;
    for(; b ; b >>= 1 , a = static_cast<i64>(a) * a % Mod){
        if(b & 1){
            res = static_cast<i64>(res) * a % Mod;
        }
    }
    return res;
}

inline void NTT(i32 *y , i32 len , i32 opt){
    i32 *rev = new int[len];
    rev[0] = 0;
    for(i32 i = 1;i < len;i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * (len >> 1));
    for(i32 i = 0;i < len;i ++) if(rev[i] > i) swap(y[rev[i]] , y[i]);
    for(i32 i = 1;i < len;i <<= 1){
        i32 G1 = quick_pow(3 , (Mod - 1) / (i << 1));
        for(i32 j = 0;j < len;j += (i << 1)){
            for(i32 k = 0 , g = 1;k < i;k ++ , g = 1LL * g * G1 % Mod){
                i32 res = static_cast<i64>(y[i + j + k]) * g % Mod;
                y[i + j + k] = ((y[j + k] - res) % Mod + Mod) % Mod;
                y[j + k] = (y[j + k] + res) % Mod;
            }
        }
    }
    if(opt == -1){
        reverse(y + 1 , y + len);
        for(i32 i = 0 , inv = quick_pow(len , Mod - 2);i < len;i ++) y[i] = 1LL * y[i] * inv % Mod;
    }
    delete []rev; rev = 0x0;
}

#define init() \
{ \
    pia[0] = 1 , pia[1] = 2; \
    for(i32 i = 2;i <= len;i ++) \
    { \
        pia[i] = 1LL * pia[i - 1] * 2 % mod; \
    } \
}

inline int Ame_(){
#ifdef AME__
    freopen(".in" , "r" , stdin); freopen(".out" , "w" , stdout); int nol_cl = clock();
#endif
    scanf("%s" , s) , n = strlen(s); res[0] = '#';
    for(i32 i = 0;i < n;i ++) res[++ cnt] = '|' , res[++ cnt] = s[i];
    res[++ cnt] = '|';
    for(i32 l = 1 , r = 0 , mid = 0;l <= cnt;l ++){
        if(l <= r) p[l] = min(p[2 * mid - l] , r - l + 1);
        else p[l] = 1;
        while(res[l - p[l]] == res[l + p[l]]) p[l] ++;
        if(l + p[l] - 1 > r) r = l + p[l] - 1 , mid = l;
    }
    for(i32 i = 1;i <= cnt;i ++) ans = (ans - p[i] / 2 + mod) % mod; 
    for(len = 1 ; len <= 2 * n ; len <<= 1); init();
    for(i32 i = 0;i < n;i ++) if(s[i] == 'a') g[i] = 1;
    NTT(g , len , 1);
    for(i32 i = 0;i < len;i ++) g[i] = static_cast<i64>(g[i]) * g[i] % Mod;
    NTT(g , len , -1);
    for(i32 i = 0;i < n;i ++) if(s[i] == 'b') h[i] = 1;
    NTT(h , len , 1);
    for(i32 i = 0;i < len;i ++) h[i] = static_cast<i64>(h[i]) * h[i] % Mod;
    NTT(h , len , -1);
    for(i32 i = 0;i < len;i ++) f[i] = (g[i] + h[i]) % mod;
    for(i32 i = 0;i < len;i ++) ans = (ans + pia[(f[i] + 1) >> 1] - 1) % mod;
    TOWA("%d\n" , ans);
#ifdef AME__TIME
    LOG("Time: %dms\n", int((clock() - nol_cl) / (qwq)CLOCKS_PER_SEC * 1000));
#endif
    return ~~(0^_^0); /*さようならプログラム*/
}
    
int Ame__ = Ame_();
    
int main(){;}
posted @ 2021-02-19 21:49  Ame_sora  阅读(57)  评论(0编辑  收藏  举报