Description

一个ab串,问有多少回文子序列,字母和位置都对称,并且不连续.

Sol

FFT+Manacher.

不连续只需要减去连续的就可以了,连续的可以直接Manacher算出来.

其他全部对称的回文子序列就可以用生成函数那样FFT搞出来,把ab分开考虑就行.

有挺多细节的...包括下标运算什么什么的...

Code

/**************************************************************
Problem: 3160
User: BeiYu
Language: C++
Result: Accepted
Time:3868 ms
Memory:29616 kb
****************************************************************/ #include <bits/stdc++.h>
using namespace std; #define mpr make_pair
#define rr first
#define ii second
typedef pair< double,double > Complex;
typedef long long LL;
const int N = 5e5+50;
const long long p = 1e9+7;
const double Pi = M_PI; Complex operator + (const Complex &a,const Complex &b) {
return mpr(a.rr+b.rr,a.ii+b.ii);
}
Complex operator - (const Complex &a,const Complex &b) {
return mpr(a.rr-b.rr,a.ii-b.ii);
}
Complex operator * (const Complex &a,const Complex &b) {
return mpr(a.rr*b.rr-a.ii*b.ii,a.rr*b.ii+a.ii*b.rr);
} int n,l;
LL ans;
int f[N],g[N];
char t[N],s[N];
Complex a[N],b[N],c[N]; LL Pow(LL a,LL b,LL r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; }
void Manacher(char *t) {
int ll=0;
for(int i=0;i<l;i++) s[ll++]='#',s[ll++]=t[i];
s[0]='$',s[ll++]='@'; for(int i=0,j=0,mx=0;i<ll;i++) {
if(mx>i) f[i]=min(mx-i,f[j*2-i]);else f[i]=1;
while(i+f[i]<ll && i-f[i]>=0 && s[i+f[i]]==s[i-f[i]]) f[i]++;
if(i+f[i]>mx) mx=i+f[i],j=i;
}
} void init(int x) {
for(n=1;n<x;n<<=1);n<<=1;
}
void Rev(Complex a[]) {
for(int i=0,j=0;i<n;i++) {
if(i>j) swap(a[i],a[j]);
for(int k=n>>1;(j^=k)<k;k>>=1);
}
}
void DFT(Complex a[],int r=1) {
Rev(a);
for(int i=2;i<=n;i<<=1) {
Complex wi=mpr(cos(2.0*Pi/i),r*sin(2.0*Pi/i));
for(int k=0;k<n;k+=i) {
Complex w=mpr(1.0,0.0);
for(int j=k;j<k+i/2;j++) {
Complex t1=a[j],t2=w*a[j+i/2];
a[j]=t1+t2,a[j+i/2]=t1-t2;
w=w*wi;
}
}
}
if(r==-1) for(int i=0;i<n;i++) a[i].rr/=n;
}
void FFT(Complex a[],Complex b[],Complex c[]) {
DFT(a),DFT(b);
for(int i=0;i<n;i++) c[i]=a[i]*b[i];
DFT(c,-1);
} int main() {
scanf("%s",t);
l=strlen(t);
init(l);
for(int i=0;i<l;i++) a[i]=mpr(t[i]=='a',0),b[i]=a[i];
// reverse(b,b+l); // for(int i=0;i<n;i++) cout<<(int)a[i].rr<<" ";cout<<endl;
// for(int i=0;i<n;i++) cout<<(int)b[i].rr<<" ";cout<<endl; FFT(a,b,c); for(int i=0;i<n;i++) g[i]=(int)(c[i].rr+0.5);
// for(int i=0;i<n;i++) cout<<(int)(c[i].rr+0.5)<<" ";cout<<endl; memset(a,0,sizeof(a)),memset(b,0,sizeof(b));
for(int i=0;i<l;i++) a[i]=mpr(t[i]=='b',0),b[i]=a[i];
// reverse(b,b+l); // for(int i=0;i<n;i++) cout<<(int)a[i].rr<<" ";cout<<endl;
// for(int i=0;i<n;i++) cout<<(int)b[i].rr<<" ";cout<<endl; FFT(a,b,c); for(int i=0;i<n;i++) g[i]+=(c[i].rr+0.5);
// for(int i=0;i<n;i++) cout<<(int)(c[i].rr+0.5)<<" ";cout<<endl; for(int i=0;i<n;i++) g[i]=(g[i]+1)/2;
// for(int i=0;i<n;i++) cout<<g[i]<<" ";cout<<endl; Manacher(t);
// for(int i=0;i<n;i++) cout<<f[i]<<" ";cout<<endl; for(int i=0;i<l*2+1;i++) if(!(i&1)) f[i]-=1;
// for(int i=0;i<n;i++) cout<<f[i]<<" ";cout<<endl; for(int i=0;i<l*2-1;i++) ans=(ans+Pow(2,g[i])-(f[i+1]+1)/2-1)%p; cout<<ans<<endl; return 0;
}
/*
abaabaa
14 aaabbbaaa
44 aaaaaaaa
53
*/

  

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 万径人踪灭——FFT

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

  5. bzoj 3160 万径人踪灭 FFT

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

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

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

  7. BZOJ 3160 万径人踪灭 解题报告

    这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...

  8. bzoj 3160: 万径人踪灭【FFT+manacher】

    考虑正难则反,我们计算所有对称子序列个数,再减去连续的 这里减去连续的很简单,manacher即可 然后考虑总的,注意到关于一个中心对称的两点下标和相同(这样也能包含以空位为对称中心的方案),所以设f ...

  9. 【BZOJ 3160】 3160: 万径人踪灭 (FFT)

    3160: 万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1440  Solved: 799 Description Input Outp ...

随机推荐

  1. VS2015下如何用编译、调试程序。

    VS2015下如何用编译.调试程序. (通过实践给出截图) 安装步骤: 下载安装网址[VS2015下载地址](http://www.ithome.com/html/win10/164028.htm) ...

  2. 可跨域的单点登录(SSO)实现方案【附.net代码】

    SSO简介 定义: 传统的单站点登录访问授权机制是:登录成功后将用户信息保存在session中,sessionId保存在cookie中,每次访问需要登录访问的资源(url)时判断当前session是否 ...

  3. 在 sublime 中运行 JavaScript 代码

    安装 Node 环境,参考 Node.js入门 打开 Sublime,选择 Tools > Build System > New Build System... 会打开一个新的文件,粘贴以 ...

  4. LISA介绍及其使用方法

    LISA是ARM公司开发的一款开源工具.在内核开发过程中,苦于无法针对修改内容进行一些量化或者可视化结果的测量,而无感.LISA对于模型调优,回归测试都有较强的支持. 什么是LISA? LISA是Li ...

  5. 华为5G空口新技术(2015年)

    2015-03-24 长江后浪推前浪,4G建设方兴未艾,业界关于5G的讨论已如火如荼.对于每一代移动通信,空口技术都相当于王冠上的明珠. 在月初的世界移动通信大会上,华为发布了面向5G的新空口,并展出 ...

  6. 文件上传之——用SWF插件实现文件异步上传和头像截取

    之前写过几篇文件上传,那些都不错.今天小编带领大家体会一种新的上传方法,及使用Flash插件实现文件上传. 使用Flash的好处就是可以解决浏览器兼容性问题.之前我写的一个快捷复制功能也是利用的Fla ...

  7. [转] eclipse SVN中文件修改后图标不变黑星解决

    原文地址:http://blog.csdn.net/luwei42768/article/details/39225641 版权声明:本文为博主原创文章,未经博主允许不得转载. 如上图, 如果文件修改 ...

  8. javascript-- test() 匹配正则 与 逻辑运算符 “!”

    在使用正则表达式验证"时分秒"的时候遇到了一个问题,因为业务需求,需要提供两个input 给用户输入开始时间和结束时间. js 代码: var regtime=/^([0-1]?[ ...

  9. Android测试基础题(三)

    今天接着给大家带来的是Android测试基础题(三).    需求:定义一个排序的方法,根据用户传入的double类型数组进行排序,并返回排序后的数组 俗话说的好:温故而知新,可以为师矣 packag ...

  10. SQLIte Transaction

    基本概念 事务(Transaction)是指一个或多个更改数据库的扩展.例如,如果您正在创建一个记录或者更新一个记录或者从表中删除一个记录,那么您正在该表上执行事务.重要的是要控制事务以确保数据的完整 ...