BZOJ 3160 万径人踪灭

2023-11-10 21:41
文章标签 bzoj 万径 人踪 3160

本文主要是介绍BZOJ 3160 万径人踪灭,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

Input

Output

Sample Input

Sample Output

HINT

先在串中两两之间插入#,形成新串s,主要是考虑中心不在列上
令$f[i]$表示以i为中心,两边为a或b且相同的对数
$f[i]=\sum_{x+y=i*2}[s[x]==s[y]]$
注意$s[x]s[y]$不能为#
发现这其实是一个卷积,于是FFT,求出f[i]
于是通过f[i]算出答案
$Ans=\sum_{i=1}^{n}2^{f[i]}-1$
因为不能连续,减去连续的回文串数,用manacher
但有几个细节:
每对(x,y)其实等价于(y,x),所以要除2
然而当s[i]不是#,实际上因为$i+i=2×i$
只算了一次,当s[i]不是#时,f[i]要-1再除2再+1
如果s[i]是#就直接除2

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<complex>
  7 using namespace std;
  8 typedef complex<double> dob;
  9 typedef long long lol;
 10 double pi=acos(-1.0);
 11 const int NN=1000000;
 12 int Mod=1000000007;
 13 dob a[NN],b[NN];
 14 int lg,R[NN],n,tot,N,f[NN],pw[NN];
 15 lol ans;
 16 char ch[NN],s[NN];
 17 int qpow(int x,int y)
 18 {
 19   int res=1;
 20   while (y)
 21     {
 22       if (y&1) res=1ll*res*x%Mod;
 23       x=1ll*x*x%Mod;
 24       y>>=1;
 25     }
 26   return res;
 27 }
 28 void FFT(dob *A,int len,double o)
 29 {int i,j,k;
 30   for (i=0;i<len;i++)
 31     if (i<R[i]) swap(A[i],A[R[i]]);
 32   for (i=1;i<len;i<<=1)
 33     {
 34       dob wn(cos(pi/i),sin(o*pi/i)),x,y;
 35       for (j=0;j<len;j+=(i<<1))
 36     {
 37       dob w(1,0);
 38       for (k=0;k<i;k++,w*=wn)
 39         {
 40           x=A[j+k];y=w*A[j+k+i];
 41           A[j+k]=x+y;
 42           A[j+k+i]=x-y;
 43         }
 44     }
 45     }
 46 }
 47 lol manacher()
 48 {lol i,len[800001];
 49   lol mx=0,po=0;
 50   lol as=0;
 51   for (i=1;i<N;i++)
 52     {
 53       if (mx>i)
 54     len[i]=min(mx-i,len[2*po-i]);
 55       else len[i]=1;
 56       while (i-len[i]>=0&&i+len[i]<=N&&s[i-len[i]]==s[i+len[i]]) len[i]++;
 57       if (len[i]+i>mx)
 58     {
 59       po=i;
 60       mx=len[i]+i;
 61     }
 62       if (s[i]!='#') as+=(len[i]-1)/2+1;
 63       else as+=(len[i]-1)/2;
 64       as%=Mod;
 65     }
 66   return as;
 67 }
 68 int main()
 69 {int i,len;
 70   scanf("%s",ch);
 71   n=strlen(ch);
 72   tot=-1;
 73   for (i=0;i<n;i++)
 74     {
 75       s[++tot]='#';
 76       s[++tot]=ch[i];
 77     }
 78   s[++tot]='#';s[++tot]='$';
 79   N=tot;
 80   len=1;
 81   while (len<=2*N) len*=2,lg++;
 82   for (i=0;i<len;i++)
 83     R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1));
 84   for (i=0;i<len;i++)
 85     a[i]=(double)(s[i]=='a');
 86   FFT(a,len,1);
 87   for (i=0;i<len;i++)
 88     b[i]=a[i]*a[i];
 89   for (i=0;i<len;i++)
 90     a[i]=(double)(s[i]=='b');
 91   FFT(a,len,1);
 92   for (i=0;i<len;i++)
 93     b[i]+=a[i]*a[i];
 94   FFT(b,len,-1);
 95   for (i=0;i<N;i++)
 96     f[i]=((int)(b[i*2].real()/(double)len+0.5)-(s[i]!='#'))>>1;
 97   pw[0]=1;
 98   for (i=1;i<=n;i++)
 99     pw[i]=pw[i-1]*2%Mod;
100   for (i=1;i<N;i++)
101     {
102       lol res=pw[f[i]]-1;
103       if (s[i]!='#') res=res*2%Mod+1;
104       ans+=res;
105       if (ans>=Mod) ans-=Mod;
106     }
107   printf("%lld\n",(ans-manacher()+Mod)%Mod);
108 }

 

转载于:https://www.cnblogs.com/Y-E-T-I/p/8385186.html

这篇关于BZOJ 3160 万径人踪灭的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/385426

相关文章

【BZOJ】1324 Exca王者之剑 最大权独立集

传送门:【BZOJ】1324  Exca王者之剑 题目分析:赤裸裸的最大权独立集。。。最小割解决 代码如下: #include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , a , b ) for ( int

【BZOJ】1026: [SCOI2009]windy数 数位DP

传送门:【BZOJ】1026: [SCOI2009]windy数 题目分析:数位DP水题。 代码如下: #include <stdio.h>#include <cstring>#include <algorithm>#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )#define For( i ,

【BZOJ】2152: 聪聪可可 点分治

传送门:【BZOJ】2152: 聪聪可可 题目分析:记录权值和%3的路径的个数。。。然后去重。。没了。。 代码如下: #include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std ;typedef lo

BZOJ 2440 2301 莫比乌斯应用

http://www.lydsy.com/JudgeOnline/problem.php?id=2440 Description 小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些 数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而 这丝毫不影响他对其他数的热爱。  这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一 个小X讨厌

3160. 所有球里面不同颜色的数目(java)

3160. 所有球里面不同颜色的数目(java) Java hashmap的merge方法: 1.merge是直接运行修改的,比如 if(colors.merge(curc,-1,Integer::sum)==0) ,不论结果真假,这个curc对应的值已经减一了。 2.字典的size和remove方法; 3. HashMap<Integer,Integer> balls = new HashMa

BZOJ 3732: Network(最小生成树+倍增)

题目链接 题意:给出一个图,每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少 很明显最终查询的边一定是在最小生成树里面的,先跑出最小生成树,然后,可以树链剖分,也可以使用倍增来计算 #include<bits/stdc++.h>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#define

BZOJ 2038 小Z的袜子(hose) (莫队离线)

题目地址:BZOJ 2038 裸的莫队算法。 代码如下: #include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>#in

BZOJ 2152 聪聪可可 (树上点分治)

题目地址:BZOJ 2152 找有多少对权值和为3的倍数的点。最简单的点分治。 代码如下: #include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#incl

BZOJ 3530 数数【AC自动机+数位dp】

[Sdoi2014]数数 简单数位dp+简单AC自动机 反正数位DP是队友写的 AC自动机要记录两个值,一个是是否为一个串的结束,即不合法状态,一个是前缀零的情况。 // whn6325689// Mr.Phoebe// http://blog.csdn.net/u013007900#include <algorithm>#include <iostr

BZOJ 3531 旅行【树链剖分】

[Sdoi2014] 简单的树链剖分 以每个信仰应该建一个线段树,空间复杂度为 O(5×1010) O(5\times 10^{10}) 因此会爆空间,所以需要动态申请空间。 // whn6325689// Mr.Phoebe// http://blog.csdn.net/u013007900#include <algorithm>#include <