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. js随机产生区间数

    function selectFrom(startNumber, endNumber) { //1.从几开始 2.到几结束 var choice = endNumber - startNumber + ...

  2. Sqoop导入导出的几个例子

    Sqoop导入导出的几个例子 http://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html#_importing_data_into_hive   no ...

  3. Dig out WeChat deleted chat messages on Android Phone

    As we know that WeChat will wipe deleted chat messages. That's why forensic guys could  not dig out ...

  4. redis常见命令使用

    这篇经验主要介绍了Redis常见用的一些操作命令.这篇例子是在windows上操作的.linux类似.写的一些基础,大神就别看了. 工具/原料   redis windows 方法/步骤   1 可以 ...

  5. 可变数目参数----关键字params的使用

    如何定义和使用可变数目参数的方法,使用关键字params. 即其他语言的可变参数 Code public class App { static void Main() { //常规使用方法 Conso ...

  6. Flexible Box布局基础知识详解

    1.基本概念,借用阮一峰老师的一张图: 容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis).主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫 ...

  7. zTree节点重叠或者遮挡

    ztree官网:http://www.treejs.cn/v3/api.php 问题:zTree节点重叠或者遮挡. 分析:由于zTree和bootstrap插件样式冲突导致的树重叠问题. 解决:设置z ...

  8. HttpServletRequest cannot be resolved to a type。

    问题描述:HttpServletRequest cannot be resolved to a type.Multiple markers at this line - The import java ...

  9. WinForm中,设置不显示窗口的标题栏

    1:ControlBox设置False,然后标题为""的时候标题就不显示了2:把窗体设置为无边的窗体 FormBoderStyle 设为 None  (在Mdi中,关闭按钮会还在) ...

  10. 2017-06-27(useradd usermod userdel 禁止普通用户登录)

    useradd useradd  -g  组名  用户名  (添加新用户,并将其添加到指定的主用户组) useradd  -g  组名  -G 附属组名  用户名  (添加新用户,并将其添加至指定主用 ...