BZOJ 3160 万径人踪灭 解题报告
这个题感觉很神呀。将 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 万径人踪灭 解题报告的更多相关文章
- BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher
BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...
- bzoj 3160: 万径人踪灭 manachar + FFT
3160: 万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 133 Solved: 80[Submit][Status][Discuss] ...
- BZOJ 3160: 万径人踪灭 [fft manacher]
3160: 万径人踪灭 题意:求一个序列有多少不连续的回文子序列 一开始zz了直接用\(2^{r_i}-1\) 总-回文子串 后者用manacher处理 前者,考虑回文有两种对称形式(以元素/缝隙作为 ...
- BZOJ 3160: 万径人踪灭
Description 一个ab串,问有多少回文子序列,字母和位置都对称,并且不连续. Sol FFT+Manacher. 不连续只需要减去连续的就可以了,连续的可以直接Manacher算出来. 其他 ...
- BZOJ 2959: 长跑 解题报告
2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...
- bzoj 3160 万径人踪灭——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 似乎理解加深了. 用卷积算相同的位置:先把 a 赋成1. b 赋成0,卷积一遍:再把 ...
- bzoj 3160 万径人踪灭 FFT
万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1936 Solved: 1076[Submit][Status][Discuss] De ...
- bzoj 3160 万径人踪灭 —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 求出关于一个位置有多少对对称字母,如果 i 位置有 f[i] 对,对答案的贡献是 2^ ...
- BZOJ 4238 电压 解题报告
BZOJ 4238 电压 考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环 则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上. 考虑建出dfs树,那么返祖边一定 ...
随机推荐
- Ehcache(2.9.x) - API Developer Guide, Cache Decorators
About Cache Decorators Ehcache uses the Ehcache interface, of which Cache is an implementation. It i ...
- Eclipse配置安卓开发环境(解决SDK manager下载慢问题)
Android新手在eclipse搭建安卓开发环境基本都会遇到Android SDK manager下载慢,ADT下载慢的问题,本文将带大家完整的安装一遍开发环境 工具:eclipse SDK ...
- 【Android】ADB常用指令与logcat日志(转)
ADB命令简介 ADB是一个功能强大的命令行工具.通过它可以直接和模拟器或真机进行交互.它是一个具有客户端和服务器端的程序. 它主要由三个部分组成: 客户端,它运行在你的开发机上,你可以通过执行adb ...
- Cocos2d-x数据持久化-查询数据
数据查询一般会带有查询条件,这可以使用SQL语句的where子句实现,但是在程序中需要动态绑定参数给where子句.查询数据的具体操作步骤如下所示.(1) 使用sqlite3_open函数打开数据库. ...
- Cocos2d-x中使用音频CocosDenshion引擎介绍与音频文件的预处理
Cocos2d-x提供了一个音频CocosDenshion引擎,CocosDenshion引擎可以独立于Cocos2d-x单独使用,CocosDenshion引擎本质上封装了OpenAL音频处理库.具 ...
- easyui combobox 模糊检索数据并填充
$("#id"),combobox({ url:'', ...... filter:function(q,row){ var op = $(this).combobox(&qu ...
- (转)Mongodb相对于关系型数据库的优缺点
与关系型数据库相比,MongoDB的优点:①弱一致性(最终一致),更能保证用户的访问速度:举例来说,在传统的关系型数据库中,一个COUNT类型的操作会锁定数据集,这样可以保证得到“当前”情况下的精确值 ...
- html5笔记
出处:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html HTML5 LocalStorage 本地存储 HTML5 ...
- poj 2220 Sumsets
Sum ...
- makefile missing separator. Stop
ifneq ($(KERNELRELEASE),) obj-m := hello.o else PWD := $(shell pwd) KVER := $(shell uname -r) KDIR : ...