• bzoj3160


    fft+manacher

    fft都快忘了。。。

    其实我们发现,这个问题是可以用fft做的,因为是回文子序列,所以我们直接自己和自己求卷积,然后扫描每个位置,注意是每个位置,因为包括奇数长度和偶数长度,f[i]为第i个位置上的对称字符的数量,那么一共就有(2^f[i])-1个回文子序列,因为是要不连续的,所以用manacher求出连续的就行了

     
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 400010, mod = 1000000007;
    const double pi = acos(-1);
    int n, m, pos, mx, len, L;
    complex<double> a[N], b[N];
    int r[N], p[N], f[N];
    ll pw[N];
    ll ans;
    char s[N], t[N];
    void fft(complex<double> *a, int f)
    {
        for(int i = 0; i < n; ++i) if(i < r[i]) swap(a[i], a[r[i]]);
        for(int i = 1; i < n; i <<= 1)
        {
            complex<double> t(cos(pi / i), f * sin(pi / i));
            for(int p = i << 1, j = 0; j < n; j += p)
            {
                complex<double> w(1, 0);
                for(int k = 0; k < i; ++k, w *= t)
                {
                    complex<double> x = a[j + k], y = w * a[j + k + i];
                    a[j + k] = x + y;
                    a[j + k + i] = x - y; 
                }
            }
        }   
    }
    int main()
    {
        scanf("%s", t);
        n = strlen(t);
        s[0] = '-';
        s[len = 1] = '#';
        for(int i = 0; i < n; ++i) s[++len] = t[i], s[++len] = '#';
        for(int i = 1; i <= len; ++i)
        {
            if(mx > i) p[i] = min(mx - i, p[2 * pos - i]);
            while(s[i + p[i]] == s[i - p[i]]) ++p[i];
            if(i + p[i] > mx)
            {
                pos = i;
                mx = i + p[i];
            }
            ans -= p[i] >> 1;
        } 
        len = n;
        m = 2 * n;
        for(n = 1; n <= m; n <<= 1) ++L;
        for(int i = 0; i < n; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));
        for(int i = 0; i < len; ++i) a[i] = (t[i] == 'a' ? 1 : 0), b[i] = (t[i] == 'b' ? 1 : 0);
        fft(a, 1);
        fft(b, 1);
        for(int i = 0; i < n; ++i) a[i] *= a[i], b[i] *= b[i];
        fft(a, -1);
        fft(b, -1);
        pw[0] = 1ll;
        for(int i = 1; i <= n; ++i) pw[i] = (pw[i - 1] << 1ll) % mod;
        for(int i = 0; i < m - 1; ++i) 
        {
            int x = (int)(a[i].real() / n + 0.5), y = (int)(b[i].real() / n + 0.5);
            ans = (ans + pw[(x + y + 1) >> 1] - 1) % mod;
        }   
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    学而201205期先导班信息系统项目管理师招生简章
    201205期蘑菇班信息系统项目管理师招生简章
    用常识驳倒方舟子之一 :韩寒的女儿与常识
    学而201211期蘑菇班信息系统项目管理师招生简章
    工作量与工作历时计算
    git设置中英文
    楼层跳转scrollintoview坑
    一则浏览器兼容性解决案例(搜狗)
    C语言未初始化变量输出的是随即数
    远程关机,在MM面前显摆一次的机会,别错过 To Phper
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7565593.html
Copyright © 2020-2023  润新知