码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ 3160] 万径人踪灭

时间:2017-08-25 19:59:43      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:work   register   scanf   pow   logs   gis   有用   class   swap   

题意

  给定一个长度为 n , 由 ‘a‘, ‘b‘ 组成的字符串 S .

  问有多少个子序列, 满足:

    ① 坐标对称.

    ② 字符对称.

    ③ 不连续.

  n <= 100000 .

 

分析

  坐标对称, 则要满足对应坐标的值相同.

  满足①② 的所有用 FFT 求.

  满足①②!③ 的所有用 Manacher 求.

 

实现

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cctype>
  5 #include <cmath>
  6 #include <algorithm>
  7 using namespace std;
  8 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
  9 #define db double
 10 
 11 const int N = 300000;
 12 const int MOD = (int)1e9+7;
 13 const db PI = acos(-1);
 14 
 15 char s[N]; int n, sum;
 16 
 17 char t[N]; int nT, E[N];
 18 void Manacher(void) {
 19     nT = n<<1|1, t[0] = <, t[1] = +, t[nT+1] = >;
 20     F(i, 1, n) t[i<<1] = s[i], t[i<<1|1] = +;
 21     
 22     for (int i = 1, id = 0; i <= nT; i++) {
 23         int j = (id+E[id]-1 <= i ? 1 : min(E[id+id-i], id+E[id]-i));
 24         while (t[i+j] == t[i-j]) j++;
 25         E[i] = j;
 26         if (id+E[id] < i+E[i]) id = i;
 27     }
 28     
 29     F(i, 1, nT)
 30         sum = (sum - (E[i] >> 1)) % MOD;
 31 }
 32 
 33 int Pow[N], cnt[N];
 34 struct Comp {
 35     db x, y;
 36     friend inline Comp operator + (Comp A, Comp B) { return (Comp){A.x + B.x, A.y + B.y}; }
 37     friend inline Comp operator - (Comp A, Comp B) { return (Comp){A.x - B.x, A.y - B.y}; }
 38     friend inline Comp operator * (Comp A, Comp B) { return (Comp){A.x * B.x - A.y * B.y, A.x * B.y + A.y * B.x}; }
 39 }A[N], B[N], rot[N][2];
 40 int Bit, Len, Rev[N];
 41 
 42 void FFT(Comp *A, int sign) {
 43     F(i, 0, Len - 1)
 44         if (i < Rev[i])
 45             swap(A[i], A[Rev[i]]);
 46     for (int i = 2; i <= Len; i <<= 1) {
 47         Comp wn = rot[i][sign];
 48         for (int j = 0; j < Len; j += i) {
 49             Comp w = (Comp){1, 0};
 50             F(k, 0, i/2-1) {
 51                 Comp x = A[j+k], y = w * A[j+k+i/2];
 52                 A[j+k] = x+y, A[j+k+i/2] = x-y;
 53                 w = w * wn;
 54             }
 55         }
 56     }
 57     if (sign == 1)
 58         F(i, 0, Len-1)
 59             A[i] = (Comp){A[i].x / Len, 0};
 60 }
 61 void Work(void) {
 62     Pow[0] = 1;
 63     F(i, 1, n) Pow[i] = (Pow[i-1] << 1) % MOD;
 64     
 65     for (Bit = 0, Len = 1; Len <= n+n; Bit++, Len <<= 1);
 66     F(i, 1, Bit) {
 67         int k = 1 << i;
 68         rot[k][0] = (Comp){cos(2 * PI / +k), sin(2 * PI / +k)};
 69         rot[k][1] = (Comp){cos(2 * PI / -k), sin(2 * PI / -k)};
 70     }
 71     F(i, 1, Len-1) Rev[i] = Rev[i >> 1] >> 1 | (i & 1) << (Bit - 1);
 72     
 73     F(i, 1, n)
 74         A[i] = (Comp){s[i] == a, 0}, B[i] = (Comp){s[i] == b, 0};
 75     
 76     FFT(A, 0);
 77     FFT(B, 0);
 78     F(i, 0, Len-1)
 79         A[i] = A[i] * A[i] + B[i] * B[i];
 80     FFT(A, 1);
 81     
 82     F(i, 1, n) cnt[i << 1]++;
 83     F(i, 2, n + n) {
 84         cnt[i] += (int)(A[i].x + 0.5);
 85         cnt[i] >>= 1;
 86         sum = (sum + Pow[cnt[i]] - 1) % MOD;
 87     }
 88 }
 89 
 90 int main(void) {
 91     #ifndef ONLINE_JUDGE
 92         freopen("bzoj3160.in", "r", stdin);
 93     #endif
 94     
 95     scanf("%s", s+1);
 96     n = strlen(s+1);
 97     
 98     Manacher();
 99     Work();
100     printf("%d\n", (sum + MOD) % MOD);
101     
102     return 0;
103 }

 

[BZOJ 3160] 万径人踪灭

标签:work   register   scanf   pow   logs   gis   有用   class   swap   

原文地址:http://www.cnblogs.com/Sdchr/p/7429422.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!