zoukankan      html  css  js  c++  java
  • 【洛谷】P4199 万径人踪灭

    题解

    每种字符跑一遍FFT,得到(i + j = k)时匹配的个数(要÷2,对于相同位置的最后再加上

    然后算出(2^{cnt[k]})的和,最后再减去用mancher匹配出的连续回文子串的个数即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    const int MOD = 998244353,MAXL = (1 << 20);
    const int M = 1000000007;
    
    int pw[400005],f[400005],N,W[MAXL + 5],ans,r[400005],mx,pos,cnt[400005];
    char s[400005];
    char t[400005];
    int fpow(int x,int c) {
        int res = 1,t = x;
        while(c) {
    	if(c & 1) res = 1LL * res * t % MOD;
    	t = 1LL * t * t % MOD;
    	c >>= 1;
        }
        return res;
    }
    void NTT(int *p,int L,int on) {
        for(int i = 1 , j = L >> 1 ; i < L - 1 ; ++i) {
    	if(i < j) swap(p[i],p[j]);
    	int k = L >> 1;
    	while(j >= k) {
    	    j -= k;
    	    k >>= 1;
    	}
    	j += k;
        }
        for(int h = 2 ; h <= L ; h <<= 1) {
    	int wn = W[(MAXL + MAXL * on / h) % MAXL];
    	for(int k = 0 ; k < L ; k += h) {
    	    int w = 1;
    	    for(int j = k ; j < k + h / 2 ; ++j) {
    		int u = p[j],t = 1LL * w * p[j + h / 2] % MOD;
    		p[j] = u + t >= MOD ? u + t - MOD : u + t;
    		p[j + h / 2] = u - t >= 0 ? u - t : u - t + MOD;
    		w = 1LL * w * wn % MOD;
    	    }
    	}
        }
        if(on == -1) {
    	int InvL = fpow(L,MOD - 2);
    	for(int i = 0 ; i < L ; ++i) p[i] = 1LL * InvL * p[i] % MOD;
        }
    }
    void Init() {
        W[0] = 1;
        W[1] = fpow(3,(MOD - 1) / MAXL);
        for(int i = 2; i < MAXL ; ++i) W[i] = 1LL * W[i - 1] * W[1] % MOD;
        pw[0] = 1;
        for(int i = 1 ; i <= 400000 ; ++i) pw[i] = 1LL * pw[i - 1] * 2 % M;
    }
    void Solve() {
        scanf("%s",s + 1);
        N = strlen(s + 1);
        for(int i = 1 ; i <= N ; ++i) {
    	if(s[i] == 'a') f[i] = 1;
        }
        int len = 1;
        while(len <= 2 * N) {len <<= 1;}
        NTT(f,len,1);
        for(int i = 0 ; i < len ; ++i) f[i] = 1LL * f[i] * f[i] % MOD;
        NTT(f,len,-1);
        for(int i = 0 ; i < len ; ++i) {
    	cnt[i] += f[i] / 2;
        }
        memset(f,0,sizeof(f));
        for(int i = 1 ; i <= N ; ++i) {
    	if(s[i] == 'b') f[i] = 1;
        }
        NTT(f,len,1);
        for(int i = 0 ; i < len ; ++i) f[i] = 1LL * f[i] * f[i] % MOD;
        NTT(f,len,-1);
        for(int i = 0 ; i < len ; ++i) {
    	cnt[i] += f[i] / 2;
        }
        for(int i = 0 ; i < len ; ++i) {
    	if(i % 2 == 0 && i / 2 >= 1 && i / 2 <= N) ++cnt[i];
    	ans = ans + pw[cnt[i]] - 1 >= M ? ans + pw[cnt[i]] - 1 - M : ans + pw[cnt[i]] - 1;
        }
        int p = 1;
        t[++p] = '$';
        for(int i = 1 ; i <= N ; ++i) {
    	t[++p] = s[i];
    	t[++p] = '$';
        }
        mx = 1,pos = 1,r[1] = 1;
        for(int i = 2 ; i <= p ; ++i) {
    	if(mx >= i) r[i] = min(r[2 * pos - i],mx - i + 1);
    	else r[i] = 1;
    	while(i + r[i] <= p && i - r[i] >= 1 && t[i + r[i]] == t[i - r[i]]) ++r[i];
    	if(i + r[i] - 1 > mx) {
    	    mx = i + r[i] - 1;
    	    pos = i;
    	}
        }
        for(int i = 1 ; i <= p ; ++i) {
    	r[i] /= 2;
    	ans = ans - r[i] >= 0 ? ans - r[i] : ans - r[i] + M;
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    
  • 相关阅读:
    Zend Framework 2.1.5 中根据服务器的环境配置调用数据库等的不同配置
    在基于 Eclipse 的 IDE 中安装和使用 Emmet(ZenCoding)
    【翻译】Emmet(Zen Coding)官方文档 之六 自定义 Emmet
    【翻译】Emmet(Zen Coding)官方文档 之二 缩写
    【翻译】Emmet(Zen Coding)官方文档 之七 一览表
    【翻译】Emmet(Zen Coding)官方文档 之三 CSS 缩写
    【翻译】Emmet(Zen Coding)官方文档 之四 动作
    【翻译】Emmet(Zen Coding)官方文档 之一 web 编程的必备工具
    Zend Framework 2 时区设置警告问题的解决
    【翻译】Emmet (Zen Coding) 元素类型
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10096179.html
Copyright © 2011-2022 走看看