3160: 万径人踪灭

题意:求一个序列有多少不连续的回文子序列


一开始zz了直接用\(2^{r_i}-1\)

总-回文子串

后者用manacher处理

前者,考虑回文有两种对称形式(以元素/缝隙作为对称轴)

f[i],i为奇数表示以缝隙对称,偶数表示以元素i>>1对称,对答案的贡献就是\(2^{f[i]}-1\)

\[f[i] = \sum_{j=1}^{i-1} [s_j = s_{i-j}]
\]

就是裸卷积

因为只有a,b两个字符,可以先后令a或b=1分别求

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define fir first
#define sec second
typedef long long ll;
const int N=(1<<19)+5, mo=1e9+7;
const double PI = acos(-1);
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
return x*f;
} struct meow{
double x, y;
meow(double a=0, double b=0):x(a), y(b){}
};
meow operator +(meow a, meow b) {return meow(a.x+b.x, a.y+b.y);}
meow operator -(meow a, meow b) {return meow(a.x-b.x, a.y-b.y);}
meow operator *(meow a, meow b) {return meow(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);}
meow conj(meow a) {return meow(a.x, -a.y);}
typedef meow cd; namespace fft {
int n, rev[N];
void ini(int lim) {
n=1; int k=0; while(n<lim) n<<=1, k++;
for(int i=0; i<n; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
}
void dft(cd *a, int flag) {
for(int i=0; i<n; i++) if(i<rev[i]) swap(a[i], a[rev[i]]);
for(int l=2; l<=n; l<<=1) {
int m = l>>1;
cd wn = cd(cos(2*PI/l), flag * sin(2*PI/l));
for(cd *p=a; p != a+n; p+=l) {
cd w(1, 0);
for(int k=0; k<m; k++) {
cd t = w * p[k+m];
p[k+m] = p[k] - t;
p[k] = p[k] + t;
w = w*wn;
}
}
}
if(flag == -1) for(int i=0; i<n; i++) a[i].x /= n;
}
void mul(cd *a) {
dft(a, 1);
for(int i=0; i<n; i++) a[i] = a[i] * a[i];
dft(a, -1);
}
} cd a[N];
int n, f[N]; ll ans;
char s[N];
ll Pow(ll a, int b) {
ll ans=1;
for(; b; b>>=1, a=a*a%mo)
if(b&1) ans=ans*a%mo;
return ans;
}
inline void mod(ll &x) {if(x<0) x+=mo; else if(x>=mo) x-=mo;} namespace ma {
int r[N]; char a[N];
ll manacher(char *s, int n) {
int p=0, a; ll ans=0;
for(int i=1; i<=n; i++) {
r[i] = i<p ? min(p-i+1, r[2*a-i]) : 1;
while(s[ i-r[i] ] == s[ i+r[i] ]) r[i]++;
if(i+r[i]-1 > p) p = i+r[i]-1, a=i;
mod(ans += r[i]>>1);
}
return ans;
}
ll cal(char *s) {
for(int i=1; i<=n; i++) a[(i<<1)-1] = '#', a[i<<1] = s[i];
a[(n<<1)+1] = '#';
a[0] = '@'; a[(n<<1)+2] = '$';
return manacher(a, (n<<1)+1);
}
} int main() {
freopen("in","r",stdin);
scanf("%s", s+1); n = strlen(s+1);
fft::ini(n+n+1);
for(int i=1; i<=n; i++) a[i].x = s[i]=='a';
fft::mul(a);
for(int i=1; i<=n+n; i++) f[i] = (int)floor(a[i].x + 0.5); for(int i=0; i<fft::n; i++) a[i] = cd(0, 0);
for(int i=1; i<=n; i++) a[i].x = s[i]=='b';
fft::mul(a);
for(int i=1; i<=n+n; i++) f[i] += (int)floor(a[i].x + 0.5);
for(int i=1; i<=n+n; i++) f[i] = (f[i]+1)>>1;
//for(int i=1; i<=n+n; i++) printf("f %d %d\n", i, f[i]); for(int i=1; i<=n+n; i++) mod(ans += Pow(2, f[i]) - 1); //printf("ans1 %lld\n", ans);
mod(ans -= ma::cal(s));
printf("%lld", ans);
}

BZOJ 3160: 万径人踪灭 [fft manacher]的更多相关文章

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

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

  2. bzoj 3160 万径人踪灭 FFT

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

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

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

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

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

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

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

  6. BZOJ 3160: 万径人踪灭

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

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

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

  8. 【BZOJ】3160: 万径人踪灭 FFT+回文串

    [题意]给定只含'a'和'b'字符串S,求不全连续的回文子序列数.n<=10^5. [算法]FFT+回文串 [题解]不全连续的回文子序列数=回文子序列总数-回文子串数. 回文子串数可以用回文串算 ...

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

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

随机推荐

  1. Can you find it?(哈希)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2141 Can you find it? Time Limit: 10000/3000 MS (Java ...

  2. Ugly Numbers(STL应用)

    题目链接:http://poj.org/problem?id=1338 Ugly Numbers Time Limit: 1000MS   Memory Limit: 10000K Total Sub ...

  3. HDU--2114

    Calculate S(n) Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. 【自制工具类】Java删除字符串中的元素

    这几天做项目需要把多个item的id存储到一个字符串中,保存进数据库.保存倒是简单,只需要判断之前是否为空,如果空就直接添加,非空则拼接个"," 所以这个字符串的数据结构是这样的 ...

  5. 关于HTTP请求出现 405状态码 not allowed的解决办法

    最近学爬虫.发现httppost请求目标网站会出现405 状态码,原因为 Apache.IIS.Nginx等绝大多数web服务器,都不允许静态文件响应POST请求 所以将post请求改为get请求即可

  6. phpstudy 虚拟主机域名配置注意问题

    第一步:hosts文件中添加对应:127.0.0.1+空格+你的域名 第二部:在D:\phpStudy \Apache\conf\vhosts.conf中禁用470行 第三部:配置域名和引入程序地址

  7. 【视频编解码·学习笔记】3. H.264视频编解码工程JM的下载与编解码

    一.下载JM工程: JM是H.264标准制定团队所认可的官方参考软件.网址如下 http://iphome.hhi.de/suehring/tml/ 从页面中可找到相应的工程源码,本次选择JM 8.6 ...

  8. [转]js 正则表达式

    一.正则表达式中包括的元素 1.原子(普通字符:a-z A-Z 0-9 .原子表. 转义字符) 2.元字符 (有特殊功能的字符) 3.模式修正符 (系统内置部分字符 i .m.S.U…) 二.正则表达 ...

  9. yum错误,Cannot find a valid baseurl for repo: base 和 No more mirrors to try

    可能出错原因: 1. yum 配置错误 2. 虚拟机无法连接外网 3. 域名解析没有 如何解决这个错误? 1. 网上找 /ect/yum.conf 和 /etc/yum.repos.d/CentOS- ...

  10. python_求1-2+3-4+......-100的值

    求1-2+3-4+5---100 = ? 逻辑整理: -- 本质上可以转换一下,1+3+5+--+99 -(2+4+--+100) 加减部分间隔都为2,先求1+3+5+--+99的值, 再求2+4+- ...