正题

题目链接:https://www.luogu.com.cn/problem/P4199


题目大意

给出一个只包含\(a,b\)的字符串

求有多少个不连续的回文子序列(字母回文,位置对称)

\(1\leq n\leq 10^5\)


解题思路

这个不连续一看就很nt,考虑求出所有的再减去连续的

对于每个对称轴来说,\(a,b\)分开考虑贡献再乘起来再减去一(两个都为空)。

加入计算\(a\)的贡献,就是看有多少对\(a\)以它为对称轴,设为\(k\)对,那么方案就是\(2^k\)。

怎么对于每个对称轴快速计算有多少对?也就是每对\(a\)都会对他们的对称轴产生贡献,假设\(i\)于\(j\)都是\(a\),那么对称轴就是\(\frac{i+j}{2}\),这个直接\(FFT\)就可以了

然后\(b\)同理。

然后字符串hash+二分计算连续的方案就好了

时间复杂度\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define ull unsigned long long
using namespace std;
const ll N=4e5+10,P=998244353,p=1e9+7;
const ull g=131;
ll n,l,a[N],b[N],r[N],ans;
ull pw[N],h[N],d[N];
char s[N];
ll power(ll x,ll b,ll P){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
void NTT(ll *f,ll op){
for(ll i=0;i<n;i++)
if(i<r[i])swap(f[i],f[r[i]]);
for(ll p=2;p<=n;p<<=1){
ll tmp=power(3,(P-1)/p,P),len=(p>>1);
if(op==-1)tmp=power(tmp,P-2,P);
for(ll k=0;k<n;k+=p){
ll buf=1;
for(ll i=k;i<k+len;i++){
ll tt=buf*f[i+len]%P;
f[i+len]=(f[i]-tt+P)%P;
f[i]=(f[i]+tt)%P;
buf=buf*tmp%P;
}
}
}
if(op==-1){
ll invn=power(n,P-2,P);
for(ll i=0;i<n;i++)
f[i]=f[i]*invn%P;
}
return;
}
ull geth(ll l,ll r)
{return h[r]-h[l-1]*pw[r-l+1];}
ull getd(ll l,ll r)
{return d[l]-d[r+1]*pw[r-l+1];}
signed main()
{
scanf("%s",s);l=strlen(s);
for(ll i=0;i<l;i++)
a[i]=(s[i]=='a'),b[i]=(s[i]=='b');
n=1;while(n<2*l)n<<=1;
for(ll i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?(n>>1):0);
NTT(a,1);NTT(b,1);
for(ll i=0;i<n;i++)a[i]=a[i]*a[i]%P,b[i]=b[i]*b[i]%P;
NTT(a,-1);NTT(b,-1);
for(ll i=0;i<n;i++)a[i]=(a[i]+1)/2,b[i]=(b[i]+1)/2;
for(ll i=0;i<n;i++)
(ans+=power(2,a[i]+b[i],p)%p-1)%=p;
pw[0]=1;
for(ll i=1;i<=l;i++)pw[i]=pw[i-1]*g;
for(ll i=1;i<=l;i++)h[i]=h[i-1]*g+s[i-1]-'a';
for(ll i=l;i>=1;i--)d[i]=d[i+1]*g+s[i-1]-'a';
for(ll i=1;i<=l;i++){
ll L=1,R=min(i,l-i+1)-1;
while(L<=R){
ll mid=(L+R)>>1;
if(geth(i-mid,i+mid)==getd(i-mid,i+mid))L=mid+1;
else R=mid-1;
}
ans-=R+1;
}
for(ll i=1;i<l;i++){
ll L=1,R=min(i,l-i);
while(L<=R){
ll mid=(L+R)>>1;
if(geth(i-mid+1,i+mid)==getd(i-mid+1,i+mid))L=mid+1;
else R=mid-1;
}
ans-=R;
}
printf("%lld\n",(ans%p+p)%p);
return 0;
}

P4199-万径人踪灭【FFT】的更多相关文章

  1. P4199 万径人踪灭 FFT + manacher

    \(\color{#0066ff}{ 题目描述 }\) \(\color{#0066ff}{输入格式}\) 一行,一个只包含a,b两种字符的字符串 \(\color{#0066ff}{输出格式}\) ...

  2. 洛谷P4199 万径人踪灭(manacher+FFT)

    传送门 题目所求为所有的不连续回文子序列个数,可以转化为回文子序列数-回文子串数 回文子串manacher跑一跑就行了,考虑怎么求回文子序列数 我们考虑,如果$S_i$是回文子序列的对称中心,那么只要 ...

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

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

  4. bzoj 3160 万径人踪灭 FFT

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

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

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

  6. 【bzoj3160】万径人踪灭 FFT

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3160 我是一个傻叉 微笑脸 #include<bits/stdc++.h> #de ...

  7. Luogu4199 万径人踪灭 FFT、Manacher

    传送门 先不考虑”不是连续的一段“这一个约束条件.可以知道:第$i$位与第$j$位相同,可以对第$\frac{i+j}{2}$位置上产生$1$的贡献(如果$i+j$为奇数表明它会对一条缝产生$1$的贡 ...

  8. 【洛谷】P4199 万径人踪灭

    题解 每种字符跑一遍FFT,得到\(i + j = k\)时匹配的个数(要÷2,对于相同位置的最后再加上 然后算出\(2^{cnt[k]}\)的和,最后再减去用mancher匹配出的连续回文子串的个数 ...

  9. BZOJ3160:万径人踪灭(FFT,Manacher)

    Solution $ans=$回文子序列$-$回文子串的数目. 后者可以用$manacher$直接求. 前者设$f[i]$表示以$i$为中心的对称的字母对数. 那么回文子序列的数量也就是$\sum_{ ...

  10. luogu P4199 万径人踪灭

    嘟嘟嘟 方案:回文子序列数 - 回文子串数. 回文子串数用manacher解决就行了,关键是怎么求会问序列数. 一个比较好的\(O(n ^ 2)\)的算法:对于一个回文中心\(i\),\(O(n)\) ...

随机推荐

  1. FileUtils 文件工具类

    FileUtils 下载jar中的文件 package com.meeno.chemical.common.utils; import lombok.extern.slf4j.Slf4j; impor ...

  2. vue项目接口管理,所有接口都在apis文件夹中统一管理

    参考:https://www.codercto.com/a/53432.html 在vue开发中,会涉及到很多接口的处理,当项目足够大时,就需要定义规范统一的接口,如何定义呢? 方法可能不只一种,本文 ...

  3. .Net Core WebApi(二)

    查看当前端口暴露的所有接口信息 https://localhost:5001/.well-known/openid-configuration 拿到信息如下

  4. go逃逸分析

    目录 1. 前言 2. 逃逸策略 3. 逃逸场景 3.1 指针逃逸 3.2 栈空间不足逃逸 3.3 动态类型逃逸 3.4 闭包引用对象逃逸 4 逃逸总结 5. 注意事项 1. 前言 所谓的逃逸分析(E ...

  5. C# 简单粗暴的毫秒转换成 分秒的格式

    C# 简单粗暴的毫秒转换成 分秒的格式 1:code(网络上很多存在拷贝或者存在bug的或者不满足自己的要求) 1 public static string RevertToTime(double m ...

  6. a、b、n为正整数且a>b,证明:若n|(a^n-b^n),则n|(a^n-b^n)/(a-b).

  7. C#新版本风格(NetCore)项目文件

    在VisualStudio中创建NetCore以上版本的项目,使用的都是新版本风格的项目文件. 和旧版本.NetFramework版本的项目文件区别: 双击项目可直接打开csproj文件进行编辑配置 ...

  8. Oracle体系结构一

    总体结构分为三个部分:SGA,PGA,FILE文件 按功能分: 存储结构  存储结构对应关系  主要文件: 数据文件: 每个数据文件只与一个数据库相关联 一个表空间可以包含一个或者多个数据文件 一个数 ...

  9. 一文带你了解.Net读写锁

    本文主要讲解.Net基于ReaderWriterLockSlim讲解读写锁 基础概念 读写锁是一个具有特殊用途的线程锁,适用于频繁读取且读取需要一定时间的场景,共享资源的读取操作通常是可以同时执行的, ...

  10. PyTorch学习笔记6--案例2:PyTorch神经网络(MNIST CNN)

    上一节中,我们使用autograd的包来定义模型并求导.本节中,我们将使用torch.nn包来构建神经网络. 一个nn.Module包含各个层和一个forward(input)方法,该方法返回outp ...