bzoj3160 万径人踪灭

原创 2018年04月15日 13:28:47

http://www.elijahqi.win/archives/3096
题目在上方链接
Description

Input

Output

Sample Input

Sample Output

HINT

Source

2013湖北互测week1

首先将字符串中间插入”#” 把他们分隔开

题目要求求不连续的回文串的个数 那么就用总数减去连续的即可 考虑连续的部分 直接用manacher求即可 算出长度 然后再/2就是答案

不连续的怎么办 考虑现在用#将他们隔开 然后假如只考虑字符是a的贡献

那么 显然字符a都会出现在偶数位置上 那么想办法知道一个位置左右对称的符合要求的字符即可得到答案 比如#a#b#a这样关于b左右对称的就是2 然后答案就是2^2-1

那么想办法计算出左右对称位置符合要求的这个t即可

设当前在第k位

f[k]=i[kimod2=0][ski=a][sk+i=a] ti[ki=2×t][ski2=a][sk+i2=a] ti[ki=2×t]stskt t[k2t>=0]stskt t=0k2stskt s即表示该串这个位置是否为a|b为的话就是1

然后两次dft一次idft即可

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define pi acos(-1)
#define ll long long
using namespace std;
const int mod=1000000007;
const int N=100020;
struct C{
    double a,b;
    inline friend C operator +(const C &x,const C &y){return (C){x.a+y.a,x.b+y.b};}
    inline friend C operator -(const C &x,const C &y){return (C){x.a-y.a,x.b-y.b};}
    inline friend C operator *(const C &x,const C &y){return (C){x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a};}
    inline void operator *=(const C &y){*this=*this*y;}
}a[N<<2],b[N<<2];
int n,m,R[N<<2],p[N<<1];ll ans;
inline void fft(C *x,int f){
    for (int i=0;i<n;++i) if (i<R[i]) swap(x[i],x[R[i]]);
    for (int i=1;i<n;i<<=1){
        C wn=(C){cos(pi/i),f*sin(pi/i)};
        for (int j=0;j<n;j+=i<<1){
            C w=(C){1,0},t1,t2;
            for (int k=0;k<i;++k,w*=wn)
                t1=x[j+k],t2=x[j+k+i]*w,x[j+k]=t1+t2,x[j+k+i]=t1-t2;
        }
    }if (f==-1) for (int i=0;i<n;++i) x[i].a/=n;
}
inline int ksm(ll b,int t){static ll tmp;tmp=1;
    for (;t;b=b*b%mod,t>>=1) if (t&1) tmp=tmp*b%mod;return tmp;
}char s[N],s1[N<<1];
template<class T>
inline void add(T &x,int v){x=x+v>=mod?x+v-mod:x+v;}
template<class T>
inline void dec(T &x,int v){x=x-v<0?x-v+mod:x-v;}
int main(){
    freopen("bzoj3160.in","r",stdin);
    scanf("%s",s+1);m=strlen(s+1);m<<=1;
    int t=0;for (n=1;n<=m;n<<=1,++t);m>>=1;
    for (int i=0;i<n;++i) R[i]=(R[i>>1]>>1)|((i&1)<<t-1);
    for (int i=1;i<=m;++i) a[i].a=s[i]=='a',b[i].a=s[i]=='b';
    fft(a,1);
//  for (int i=0;i<n;++i) printf("%f\n",a[i].a);
    fft(b,1);for (int i=0;i<n;++i) a[i]=a[i]*a[i],b[i]=b[i]*b[i],a[i]=a[i]+b[i];
    fft(a,-1);for (int i=1;i<=m;++i) s1[i*2-1]='#',s1[i<<1]=s[i];m<<=1;int mx=0,id=0;
    for (int i=2;i<=m;++i) add(ans,ksm(2,((int)(a[i].a+0.1)+1>>1))-1);s1[++m]='#';
//  for (int i=1;i<=m;++i) printf("%lf\n",a[i].a);
//  for (int i=2;i<=m;++i) printf("%d\n",(int)(a[i].a+0.1)>>1);
    for (int i=1;i<=m;++i){
        if (i<mx) p[i]=min(mx-i,p[(id<<1)-i]);else p[i]=1;
        while(i-p[i]>0&&i+p[i]<=m&&s1[i-p[i]]==s1[i+p[i]]) ++p[i];
        if(i+p[i]>mx) mx=i+p[i],id=i;dec(ans,p[i]>>1);
    }
//  for (int i=1;i<=m;++i) printf("%d ",p[i]); 
    printf("%lld\n",ans);
    return 0;
}
版权声明:辣鸡蒟蒻的blog https://blog.csdn.net/elijahqi/article/details/79948588

BZOJ 3160 万径人踪灭 FFT+Manacher

BZOJ 3160 万径人踪灭 FFT+Manacher
  • wzq_QwQ
  • wzq_QwQ
  • 2015-09-02 08:18:40
  • 2102

[BZOJ3160]万径人踪灭(FFT+manacher)

题目描述传送门题目大意:在一个只含ab的字符串中选取一个子序列,使得:1、字符和下标都关于一个中心对称2、不能是连续的一段。求方案数。题解这题我的方法好蠢啊→_→ 首先容斥一下,答案=所有子序列的方...
  • Clove_unique
  • Clove_unique
  • 2017-04-24 14:37:35
  • 442

bzoj3160: 万径人踪灭

题面传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3160 思路:首先题目中不要连续的回文串,那么答案就是总的回文串-连续回文串 连续回文...
  • thy_asdf
  • thy_asdf
  • 2015-07-21 08:17:51
  • 427

[BZOJ3160] 万径人踪灭 - FFT快速傅里叶变换 - manacher

大爷题解:BZOJ 3160 万径人踪灭         讲道理的话思路我是想到了的……然后不会manacher就现学了一发。         记得有些奇奇怪怪的地方要用long long! #...
  • whzzt
  • whzzt
  • 2016-06-04 18:39:18
  • 427

3160: 万径人踪灭|FFT|manacher

答案可以转化为所有的回文子序列减去回文子串 回文子串的个数可以用manachermanacher来求出 回文子序列的个数可以这样求: 先求出以每个点为中心左右对称的点的个数xx,那么以这个点为中...
  • ws_yzy
  • ws_yzy
  • 2016-04-07 17:19:48
  • 2512

【bzoj3160】万径人踪灭 FFT+manacher

首先把字符串用#间隔开 总数-连续的字符串 连续的用manacher求 总数如何求? f[i]表示以i为中心有多少对对称的字符(不包含#,但包含本身) ans=∑2^f[i]-n 原字符串...
  • u012288458
  • u012288458
  • 2016-03-24 20:03:07
  • 306

[BZOJ]3160 万径人踪灭 Manacher + FFT

3160: 万径人踪灭Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1753  Solved: 977[Submit][Status][Discuss...
  • MaxMercer
  • MaxMercer
  • 2018-01-17 21:48:58
  • 118

【BZOJ3160】万径人踪灭

【题目链接】点击打开链接【思路要点】枚举对称中心,设关于该中心对称点的个数为\(x\),以该点为中心的最长回文子串长度为\(y\),那么该点对答案的贡献应为\(2^x-\lfloor\frac{y+1...
  • qq_39972971
  • qq_39972971
  • 2018-02-26 16:35:18
  • 24

【BZOJ3813】【UOJ38】【清华集训2014】奇数国

【题目链接】BZOJUOJ【思路要点】首先,有一个直观的做法是对每一个质因子维护一棵树状数组,记录区间中该质因子指数的和。询问时先将\(product\)质因数分解的结果求出来,再用快速幂计算欧拉函数...
  • qq_39972971
  • qq_39972971
  • 2018-02-27 09:55:19
  • 28

bzoj3160 万径人踪灭(FFT+manacher)

题意:已知一个长度为n的字符串仅由’a’和’b’构成,求该串不连续的回文子串个数。 严格地描述,题意中的回文子串应满足: 1.位置和字符都关于某条线对称 2.该回文串不连续 解法:FFT+ma...
  • u013514182
  • u013514182
  • 2015-05-06 00:42:14
  • 232
收藏助手
不良信息举报
您举报文章:bzoj3160 万径人踪灭
举报原因:
原因补充:

(最多只允许输入30个字)