【洛谷】P4199 万径人踪灭
题解
每种字符跑一遍FFT,得到\(i + j = k\)时匹配的个数(要÷2,对于相同位置的最后再加上
然后算出\(2^{cnt[k]}\)的和,最后再减去用mancher匹配出的连续回文子串的个数即可
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 998244353,MAXL = (1 << 20);
const int M = 1000000007;
int pw[400005],f[400005],N,W[MAXL + 5],ans,r[400005],mx,pos,cnt[400005];
char s[400005];
char t[400005];
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = 1LL * res * t % MOD;
t = 1LL * t * t % MOD;
c >>= 1;
}
return res;
}
void NTT(int *p,int L,int on) {
for(int i = 1 , j = L >> 1 ; i < L - 1 ; ++i) {
if(i < j) swap(p[i],p[j]);
int k = L >> 1;
while(j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
for(int h = 2 ; h <= L ; h <<= 1) {
int wn = W[(MAXL + MAXL * on / h) % MAXL];
for(int k = 0 ; k < L ; k += h) {
int w = 1;
for(int j = k ; j < k + h / 2 ; ++j) {
int u = p[j],t = 1LL * w * p[j + h / 2] % MOD;
p[j] = u + t >= MOD ? u + t - MOD : u + t;
p[j + h / 2] = u - t >= 0 ? u - t : u - t + MOD;
w = 1LL * w * wn % MOD;
}
}
}
if(on == -1) {
int InvL = fpow(L,MOD - 2);
for(int i = 0 ; i < L ; ++i) p[i] = 1LL * InvL * p[i] % MOD;
}
}
void Init() {
W[0] = 1;
W[1] = fpow(3,(MOD - 1) / MAXL);
for(int i = 2; i < MAXL ; ++i) W[i] = 1LL * W[i - 1] * W[1] % MOD;
pw[0] = 1;
for(int i = 1 ; i <= 400000 ; ++i) pw[i] = 1LL * pw[i - 1] * 2 % M;
}
void Solve() {
scanf("%s",s + 1);
N = strlen(s + 1);
for(int i = 1 ; i <= N ; ++i) {
if(s[i] == 'a') f[i] = 1;
}
int len = 1;
while(len <= 2 * N) {len <<= 1;}
NTT(f,len,1);
for(int i = 0 ; i < len ; ++i) f[i] = 1LL * f[i] * f[i] % MOD;
NTT(f,len,-1);
for(int i = 0 ; i < len ; ++i) {
cnt[i] += f[i] / 2;
}
memset(f,0,sizeof(f));
for(int i = 1 ; i <= N ; ++i) {
if(s[i] == 'b') f[i] = 1;
}
NTT(f,len,1);
for(int i = 0 ; i < len ; ++i) f[i] = 1LL * f[i] * f[i] % MOD;
NTT(f,len,-1);
for(int i = 0 ; i < len ; ++i) {
cnt[i] += f[i] / 2;
}
for(int i = 0 ; i < len ; ++i) {
if(i % 2 == 0 && i / 2 >= 1 && i / 2 <= N) ++cnt[i];
ans = ans + pw[cnt[i]] - 1 >= M ? ans + pw[cnt[i]] - 1 - M : ans + pw[cnt[i]] - 1;
}
int p = 1;
t[++p] = '$';
for(int i = 1 ; i <= N ; ++i) {
t[++p] = s[i];
t[++p] = '$';
}
mx = 1,pos = 1,r[1] = 1;
for(int i = 2 ; i <= p ; ++i) {
if(mx >= i) r[i] = min(r[2 * pos - i],mx - i + 1);
else r[i] = 1;
while(i + r[i] <= p && i - r[i] >= 1 && t[i + r[i]] == t[i - r[i]]) ++r[i];
if(i + r[i] - 1 > mx) {
mx = i + r[i] - 1;
pos = i;
}
}
for(int i = 1 ; i <= p ; ++i) {
r[i] /= 2;
ans = ans - r[i] >= 0 ? ans - r[i] : ans - r[i] + M;
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}
【洛谷】P4199 万径人踪灭的更多相关文章
- 洛谷P4199 万径人踪灭(manacher+FFT)
传送门 题目所求为所有的不连续回文子序列个数,可以转化为回文子序列数-回文子串数 回文子串manacher跑一跑就行了,考虑怎么求回文子序列数 我们考虑,如果$S_i$是回文子序列的对称中心,那么只要 ...
- 洛咕 P4199 万径人踪灭
给了两条限制,但是第二条想想是没用的,直接manacher就可以减掉多余的部分了,所以要求满足第一条的方案 也不难,可以想到枚举每个中心点,计算两边有多少对距离中心相等的位置值也相等,假设有\(t\) ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
- 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.
没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP
题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...
- 洛谷P1710 地铁涨价
P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交 讨论 题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...
- 洛谷P1371 NOI元丹
P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交 讨论 题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...
- 洛谷P1538迎春舞会之数字舞蹈
题目背景 HNSDFZ的同学们为了庆祝春节,准备排练一场舞会. 题目描述 在越来越讲究合作的时代,人们注意的更多的不是个人物的舞姿,而是集体的排列. 为了配合每年的倒计时,同学们决定排出——“数字舞蹈 ...
- 洛谷八月月赛Round1凄惨记
个人背景: 上午9:30放学,然后因为学校举办读书工程跟同学去书城选书,中午回来开始打比赛,下午又回老家,中间抽出一点时间调代码,回家已经8:50了 也许是7月月赛时“连蒙带骗”AK的太幸运然而因同学 ...
随机推荐
- Python之Numpy数组拼接,组合,连接
转自:https://www.douban.com/note/518335786/?type=like ============改变数组的维度==================已知reshape函数 ...
- Codeforces 817
A 你可以按如下方式移动 问能不能从给定的一个坐标走到另一个. [solution] 裸,奇偶性注意 #include<stdio.h> #include<stdlib.h> ...
- Linux SSH免登陆配置步骤
[jans@centos2 ~]# cd ~[jans@centos2 ~]# ssh-keygen -t rsa //生成rsa加密的公钥和密钥[jans@centos2 ~]# cat .ssh ...
- java基础基础总结----- 数组深入理解(四)
一.数组的基本概念 数组可以看成是多个相同类型数据组合,对这些数据的统一管理. 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量. 数组的元素可以是任何数据类型,包括基 ...
- python自带的IDLE如何清屏
作者:知乎用户 链接:https://www.zhihu.com/question/20917976/answer/32876441 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...
- vue-router基本概念及使用
index.html: <!DOCTYPE html> <html> <head> <title></title> <meta cha ...
- 学了display:flex垂直居中容易多了
以前div内部的文字垂直居中,使用height = line-height,现在可以使用display:flex来实现了 .div{ display:flex; align-items:center; ...
- shift 用法
shift shift命令用于对参数的移动 (左移),通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理(常见于Linux中各种程序的启动脚本). 示例 1 示例 依次读取输入的 ...
- mybatis一对多关联查询——(九)
1.需求: 查询所有订单信息及订单下的订单明细信息. 订单信息与订单明细为一对多关系. 2. sql语句 确定主查询表:订单表 确定关联查询表:订单明细表 在一对一查询基础上添加订单明细表关 ...
- Mini Twitter
Implement a simple twitter. Support the following method: postTweet(user_id, tweet_text). Post a twe ...