这个题感觉很神呀。将 FFT 和 Manacher 有机结合在了一起。

首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ 对称的字母对的数量,那么答案(暂记为 $Ans$)就会是:

$$Ans = \sum 2^{T_i}-1$$

在不管那个 “不能连续” 的条件的时候,这个应该是显然的。

怎么算的话,我们弄两次。分别把 $a$ 和 $b$ 当做 $1$,另一个当做 $0$,然后就可以得到一个多项式,将这个多项式平方一下就可以得到所有的 $T_i$ 了,具体用 FFT 实现。

那么我们来管一管这个条件。

我们就可以用 Manacher 求出每一条直线的最长回文半径,然后记 $R_i$ 为直线 $i$ 的最长回文半径,那么实际上的总答案就会是:

$$Ans - \sum R_i$$

然后就做完啦。令 $n$ 为字符串的长度:

时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$。

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
#define N 262144 + 5
#define _Mod 1000000007
#define Mod 998244353
#define g 3 int n, len, Inv_len, d, ans, e[][N], Rev[N], A[N], T[N], R[N];
char s[N]; inline int Inc(int u, int v, int p)
{
return u + v - (u + v >= p ? p : );
} inline int power(int u, int v, int p)
{
int res = ;
for (; v; v >>= )
{
if (v & ) res = (LL) res * u % p;
u = (LL) u * u % p;
}
return res;
} inline void FFT_Prepare()
{
for (len = n << ; len != (len & -len); len += (len & -len)) ;
for (int i = len; i > ; i >>= ) d ++;
int w = power(g, (Mod - ) / len, Mod);
int Inv_w = power(w, Mod - , Mod);
Inv_len = power(len, Mod - , Mod);
for (int i = ; i < len; i ++)
{
e[][i] = !i ? : (LL) e[][i - ] * w % Mod;
e[][i] = !i ? : (LL) e[][i - ] * Inv_w % Mod;
for (int j = ; j < d; j ++)
if ((i >> j) & ) Rev[i] += << (d - j - );
}
} inline void FFT(int *p, int op)
{
for (int i = ; i < len; i ++)
if (Rev[i] > i) swap(p[Rev[i]], p[i]);
for (int k = , s = ; k < len; k <<= , s ++)
for (int i = ; i < len; i ++)
{
if (i & k) continue ;
int t = (i & (k - )) << (d - s);
int u = Inc(p[i], (LL) p[i + k] * e[op][t] % Mod, Mod);
int v = Inc(p[i], (LL) (Mod - p[i + k]) * e[op][t] % Mod, Mod);
p[i] = u, p[i + k] = v;
}
} inline void FFT_Work(char key)
{
memset(A, , sizeof(A));
for (int i = ; i < n; i ++)
A[i] = (s[i] == key);
FFT(A, );
for (int i = ; i < len; i ++)
A[i] = (LL) A[i] * A[i] % Mod;
FFT(A, );
for (int i = ; i < len; i ++)
T[i] = Inc(T[i], (LL) A[i] * Inv_len % Mod, Mod);
} inline void Manacher()
{
for (int i = (n << ); i >= ; i --)
s[i] = i & ? s[i >> ] : 'c';
int mx = -, id;
for (int i = ; i <= (n << ); i ++)
{
if (mx > i)
R[i] = min(R[id * - i], mx - i);
else R[i] = ;
for (; i + R[i] <= (n << ) && i - R[i] >= && s[i + R[i]] == s[i - R[i]]; R[i] ++) ;
if (i + R[i] > mx)
mx = i + R[i], id = i;
}
} int main()
{
scanf("%s", s);
n = strlen(s);
FFT_Prepare();
for (char ch = 'a'; ch <= 'b'; ch ++)
FFT_Work(ch);
for (int i = ; i < len; i ++)
{
T[i] = (T[i] + ) >> ;
ans = Inc(ans, power(, T[i], _Mod) - , _Mod);
}
Manacher();
for (int i = ; i <= (n << ); i ++)
ans = Inc(ans, _Mod - R[i] / , _Mod);
printf("%d\n", ans); return ;
}

3160_Gromah

BZOJ 3160 万径人踪灭 解题报告的更多相关文章

  1. BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher

    BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...

  2. bzoj 3160: 万径人踪灭 manachar + FFT

    3160: 万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 133  Solved: 80[Submit][Status][Discuss] ...

  3. BZOJ 3160: 万径人踪灭 [fft manacher]

    3160: 万径人踪灭 题意:求一个序列有多少不连续的回文子序列 一开始zz了直接用\(2^{r_i}-1\) 总-回文子串 后者用manacher处理 前者,考虑回文有两种对称形式(以元素/缝隙作为 ...

  4. BZOJ 3160: 万径人踪灭

    Description 一个ab串,问有多少回文子序列,字母和位置都对称,并且不连续. Sol FFT+Manacher. 不连续只需要减去连续的就可以了,连续的可以直接Manacher算出来. 其他 ...

  5. BZOJ 2959: 长跑 解题报告

    2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...

  6. bzoj 3160 万径人踪灭——FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 似乎理解加深了. 用卷积算相同的位置:先把 a 赋成1. b 赋成0,卷积一遍:再把 ...

  7. bzoj 3160 万径人踪灭 FFT

    万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1936  Solved: 1076[Submit][Status][Discuss] De ...

  8. bzoj 3160 万径人踪灭 —— FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 求出关于一个位置有多少对对称字母,如果 i 位置有 f[i] 对,对答案的贡献是 2^ ...

  9. BZOJ 4238 电压 解题报告

    BZOJ 4238 电压 考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环 则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上. 考虑建出dfs树,那么返祖边一定 ...

随机推荐

  1. Android之触屏事件

    方法一: 新建"MyView"类 package onTouchEvent; import android.content.Context; import android.grap ...

  2. ArcMap 10.2 crashes during Loading Document launch stage

    问题描述: ArcMap unexpectedly exits during the "Loading Document..." stage on startup. No erro ...

  3. 163免费邮客户端设置的POP3、SMTP、IMAP地址

    网易邮箱支持POP3/SMTP/IMAP服务,方便您可以通过电脑客户端软件更好地收发邮件

  4. Atl笔记二:BEGIN_COM_MAP

    1,offsetofclass获取基类相对于子类的偏移位置. #define _ATL_PACKING 8#define offsetofclass(base, derived) ((DWORD_PT ...

  5. iOS SEL的简单总结

    @interface Person : NSObject + (void)test1; - (void)test2; @end // 根据.h文件中定义的Person类和方法 执行完这行代码 在内存中 ...

  6. Ubuntu 14.04下java开发环境的搭建--2--Eclipse的安装

    前面说了JDK的安装,http://www.cnblogs.com/bcsflilong/p/4196536.html 下面我们来安装Eclipse! 安装Eclipse 的前提是,你的JDK已经安装 ...

  7. Linux C 程序 文件操作(Linux系统编程)(14)

    文件操作(Linux系统编程) 创建一个目录时,系统会自动创建两个目录.和.. C语言实现权限控制函数 #include<stdio.h> #include<stdlib.h> ...

  8. IAR ERROR --- [Li006]

    今天移植代码时遇到一个比较奇葩的问题,记录如下: Error[Li006]: duplicate definitions for "Uart3"; in "E:\IAR_ ...

  9. AngularJS(7)-表格

    ng-repeat 指令可以完美的显示表格. <!DOCTYPE html> <html lang="en"> <head> <meta ...

  10. 使用XFire+Spring构建Web Service

    XFire是与Axis 2并列的新一代Web Service框架,通过提供简单的API支持Web Service各项标准协议,帮助你方便快速地开发Web Service应用. 相 对于Axis来说,目 ...