zoukankan      html  css  js  c++  java
  • BZOJ 3160 FFT+马拉车

    题意显然

    ans=回文子序列数目 - 回文子串数目 

    回文子串直接用马拉车跑出来

    回文子序列一开始总是不知道怎么求 (太蠢了)

    后面看了题解

    构造一个神奇的卷积

    (这个是我盗的图)地址 

    后面还有一些细节需要处理出 f[x] (f[x] 表示 x左右相等的个数)

    通常我们需要的情况是 两个函数相乘 这里是s[x-i] == s[x+i] 分类讨论就行了  变成1*1=1的形式

    所以要a=1 b=0 和 a=0 b=1都算一次

    这里长度扩展了一倍 表示 当 i 是奇数时表示对称轴是元素 ,偶数表示对称轴是两个元素的间隔

    根据二项式定理 求出每一个f[x] 的贡献 expmod ( 2, ( cnt[i] + 1 ) >> 1 ) - 1 

    还有最后一个细节 相减的时候要记得加上mod 再取模

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <set>
      7 #include <iostream>
      8 #include <map>
      9 #include <stack>
     10 #include <string>
     11 #include <vector>
     12 #define  pi acos(-1.0)
     13 #define  eps 1e-9
     14 #define  fi first
     15 #define  se second
     16 #define  rtl   rt<<1
     17 #define  rtr   rt<<1|1
     18 #define  bug         printf("******
    ")
     19 #define  mem(a,b)    memset(a,b,sizeof(a))
     20 #define  name2str(x) #x
     21 #define  fuck(x)     cout<<#x" = "<<x<<endl
     22 #define  f(a)        a*a
     23 #define  sf(n)       scanf("%d", &n)
     24 #define  sff(a,b)    scanf("%d %d", &a, &b)
     25 #define  sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
     26 #define  sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d)
     27 #define  pf          printf
     28 #define  FRE(i,a,b)  for(i = a; i <= b; i++)
     29 #define  FREE(i,a,b) for(i = a; i >= b; i--)
     30 #define  FRL(i,a,b)  for(i = a; i < b; i++)+
     31 #define  FRLL(i,a,b) for(i = a; i > b; i--)
     32 #define  FIN         freopen("data.txt","r",stdin)
     33 #define  gcd(a,b)    __gcd(a,b)
     34 #define  lowbit(x)   x&-x
     35 #define rep(i,a,b) for(int i=a;i<b;++i)
     36 #define per(i,a,b) for(int i=a-1;i>=b;--i)
     37 using namespace std;
     38 typedef long long  LL;
     39 typedef unsigned long long ULL;
     40 const int maxn = 3e5 + 7;
     41 const int maxm = maxn * 4;
     42 const int mod = 1e9 + 7;
     43 int n, m, a[maxn], b[maxn];
     44 int len, res[maxm], mx; //开大4倍
     45 struct cpx {
     46     long double r, i;
     47     cpx ( long double r = 0, long double i = 0 ) : r ( r ), i ( i ) {};
     48     cpx operator+ ( const cpx &b ) {
     49         return cpx ( r + b.r, i + b.i );
     50     }
     51     cpx operator- ( const cpx &b ) {
     52         return cpx ( r - b.r, i - b.i );
     53     }
     54     cpx operator* ( const cpx &b ) {
     55         return cpx ( r * b.r - i * b.i, i * b.r + r * b.i );
     56     }
     57 } va[maxm], vb[maxm];
     58 void rader ( cpx F[], int len ) { //len = 2^M,reverse F[i] with  F[j] j为i二进制反转
     59     int j = len >> 1;
     60     for ( int i = 1; i < len - 1; ++i ) {
     61         if ( i < j ) swap ( F[i], F[j] ); // reverse
     62         int k = len >> 1;
     63         while ( j >= k ) j -= k, k >>= 1;
     64         if ( j < k ) j += k;
     65     }
     66 }
     67 void FFT ( cpx F[], int len, int t ) {
     68     rader ( F, len );
     69     for ( int h = 2; h <= len; h <<= 1 ) {
     70         cpx wn ( cos ( -t * 2 * pi / h ), sin ( -t * 2 * pi / h ) );
     71         for ( int j = 0; j < len; j += h ) {
     72             cpx E ( 1, 0 ); //旋转因子
     73             for ( int k = j; k < j + h / 2; ++k ) {
     74                 cpx u = F[k];
     75                 cpx v = E * F[k + h / 2];
     76                 F[k] = u + v;
     77                 F[k + h / 2] = u - v;
     78                 E = E * wn;
     79             }
     80         }
     81     }
     82     if ( t == -1 ) //IDFT
     83         for ( int i = 0; i < len; ++i ) F[i].r /= len;
     84 }
     85 void Conv ( cpx a[], cpx b[], int len ) { //求卷积
     86     FFT ( a, len, 1 );
     87     FFT ( b, len, 1 );
     88     for ( int i = 0; i < len; ++i ) a[i] = a[i] * b[i];
     89     FFT ( a, len, -1 );
     90 }
     91 void gao () {
     92     len = 1;
     93     mx = n + m;
     94     while ( len <= mx ) len <<= 1; //mx为卷积后最大下标
     95     for ( int i = 0; i < len; i++ ) va[i].r = va[i].i = vb[i].r = vb[i].i = 0;
     96     for ( int i = 0; i < n; i++ ) va[i].r = a[i]; //根据题目要求改写
     97     for ( int i = 0; i < m; i++ ) vb[i].r = b[i]; //根据题目要求改写
     98     Conv ( va, vb, len );
     99     for ( int i = 0; i < len; ++i ) res[i] += ( LL ) floor ( va[i].r + 0.5 );
    100 }
    101 char Ma[maxn * 2];
    102 int Mp[maxn * 2];
    103 int Manacher ( char s[], int len ) {
    104     int l = 0, ret = 0;
    105     Ma[l++] = '$';
    106     Ma[l++] = '#';
    107     for ( int i = 0; i < len; i++ ) {
    108         Ma[l++] = s[i];
    109         Ma[l++] = '#';
    110     }
    111     Ma[l] = 0;
    112     int mx = 0, id = 0;
    113     for ( int i = 0; i < l; i++ ) {
    114         Mp[i] = mx > i ? min ( Mp[2 * id - i], mx - i ) : 1;
    115         while ( Ma[i + Mp[i]] == Ma[i - Mp[i]] ) Mp[i]++;
    116         if ( i + Mp[i] > mx ) {
    117             mx = i + Mp[i];
    118             id = i;
    119         }
    120         ret += Mp[i] >> 1, ret %= mod;
    121     }
    122     return ret % mod;
    123 }
    124 LL expmod ( LL a, LL b ) {
    125     LL res = 1;
    126     while ( b ) {
    127         if ( b & 1 )  res = res * a % mod;
    128         a = a * a % mod;
    129         b = b >> 1;
    130     }
    131     return res % mod;
    132 }
    133 char s[maxn];
    134 int cnt[maxn];
    135 int main() {
    136    // FIN;
    137     scanf ( "%s", s + 1 );
    138     n = m = strlen ( s + 1 );
    139     LL ans = 0, temp = Manacher ( s + 1, n );
    140     n++, m++;
    141     for ( int i = 1 ; i < n  ; i++ ) if ( s[i] == 'a' ) a[i] = 1, b[i] = 1;
    142     gao();
    143     for ( int i = 1 ; i <= 2 * ( n - 1 ) ; i++ ) cnt[i] += res[i];
    144     mem ( a, 0 ), mem ( b, 0 ), mem ( res, 0 );
    145     for ( int i = 1 ; i < n  ; i++ ) if ( s[i] == 'b' ) a[i] = 1, b[i] = 1;
    146     gao();
    147     for ( int i = 1 ; i <= 2 * ( n - 1 ) ; i++ ) cnt[i] += res[i];
    148     for ( int i = 1 ; i <= 2 * ( n - 1 ) ; i++ )
    149         ans = ( ans + expmod ( 2, ( cnt[i] + 1 ) >> 1 ) - 1 ) % mod;
    150     printf ( "%lld
    ", ( ans - temp + mod ) % mod );
    151     return 0;
    152 }
  • 相关阅读:
    在select标签中添加a标签
    js实现input的赋值
    JS截取字符串方法实例
    javascript中onclick(this)用法和onclick(this.value)用法介绍
    cookie的设置与销毁
    Js添加、读取、删除cookie,判断cookie是否有效,指定domain域下主路径path下设置cookie,设置expires过期时间
    自然语言处理的神经网络模型初探
    [Android] Toast问题深度剖析(二)
    如何使用 scikit-learn 为机器学习准备文本数据
    Android图像处理
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/10440648.html
Copyright © 2011-2022 走看看