BZOJ3160: 萬徑人蹤滅
阿新 • • 發佈:2018-02-08
one 題意 spa b2b 背景 amp double 中間 def
n<=1e5的ab串,問對稱的不連續的回文子序列數。取模。
雖然是道卷積題但是根本看不出來耶!
好吧沒關系,要熟悉卷積那個圖形:(紅箭頭那裏是交於一點的,如果你覺得不是就是近視加深了)
好來看這個題,要是連續的可以用manacher得,所以不連續條件可先排除掉。
然後剩下的東西不就是要求這種形式的東西有多少個嘛!
說人話,$f(i)$表示對稱軸為$\frac{i}{2}$的有多少對(0.5表示對稱軸為兩個字母的中間),$p[i]=[s[i]==a]$
那麽$f_i=\sum_{j=0}^{i}p_j \ \ xor \ \ p_i$,好的,卷積!等等這不是積。。
異或的話,先設a為1,b為0,卷積算一次,再a為0,b為1,卷積算一次,加起來不久得了。。
一個$f_i$對答案貢獻是$2^{\left \lceil \frac{f_i+1}{2} \right \rceil}-1$
OK
話說這題還挺有詩意的,看背景以為是恐怖故事,結果全文一直用一種輕快的筆調來描述題意,絲毫沒有別離帶來的惆悵。這讓我想起舊時候的分別詩句:“海內存知己,天涯若比鄰”,“莫愁前路無知己,天下誰人不識君”,而筆者竟對別離一筆帶過,可謂是更勝一籌!在輕描淡寫的別離時配以濃墨重彩的景物描寫,別離之愁需如此美景才可釋懷,萬徑依在,人蹤已滅,不僅使得別離的苦悶更加濃厚,還表現了一種曠達的胸襟,妙哉!(本題分類:語文)
1 #include<cstdio> 2View Code#include<cstdlib> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstring> 6 #include<complex> 7 #include<math.h> 8 //#include<iostream> 9 using namespace std; 10 11 int n,m,wei; 12 #define maxn 262222 13 char s[maxn]; 14 const double pi=acos(-1);15 const int mod=1e9+7; 16 typedef complex<double> cp; 17 cp a[maxn],b[maxn],c[maxn]; 18 int two[maxn],p[maxn],rev[maxn]; 19 20 void dft(cp *a,int n,int type) 21 { 22 for (int i=0;i<n;i++) if (i<rev[i]) {cp t=a[i]; a[i]=a[rev[i]]; a[rev[i]]=t;} 23 for (int i=1;i<n;i<<=1) 24 { 25 cp base=cp(cos(pi/i),type*sin(pi/i)); 26 for (int j=0,p=i<<1;j<n;j+=p) 27 { 28 cp t=cp(1,0); 29 for (int k=0;k<i;k++,t*=base) 30 { 31 cp tmp=t*a[j+k+i]; 32 a[j+k+i]=a[j+k]-tmp; 33 a[j+k]+=tmp; 34 } 35 } 36 } 37 } 38 39 void mul(cp *a,cp *b) 40 { 41 if (!rev[1]) for (int i=0;i<n;i++) 42 { 43 rev[i]=0; 44 for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1); 45 } 46 dft(a,n,1); 47 for (int i=0;i<n;i++) b[i]=a[i]*a[i]; 48 dft(b,n,-1); 49 for (int i=0;i<n;i++) b[i]/=n; 50 } 51 52 int main() 53 { 54 scanf("%s",s); n=strlen(s)-1; 55 m=n+n; for (n=1,wei=0;n<=m;n<<=1,wei++); 56 two[0]=1; for (int i=1;i<=m;i++) two[i]=(two[i-1]<<1)%mod; 57 m>>=1; for (int i=0;i<=m;i++) a[i]=(s[i]==‘a‘); m<<=1; mul(a,b); 58 m>>=1; for (int i=0;i<=m;i++) a[i]=(s[i]==‘b‘); 59 for (int i=m+1;i<n;i++) a[i]=0; m<<=1; mul(a,c); 60 int ans=0; 61 for (int i=0;i<=m;i++) ans=(ans+two[((int)(b[i].real()+0.5)+(int)(c[i].real()+0.5)+1)>>1]-1)%mod; 62 63 m>>=1; n=m+1; s[n+n]=‘$‘; s[n+n+1]=‘\0‘; 64 for (int i=n-1;i>=0;i--) s[i+i+1]=s[i],s[i+i]=‘$‘; 65 p[0]=1; int id=0; 66 for (int i=1,to=n+n;i<to;i++) 67 { 68 if (p[id]+id>i) p[i]=min(p[id+id-i],p[id]+id-i); else p[i]=1; 69 while (p[i]+i<=to && i-p[i]>=0 && s[p[i]+i]==s[i-p[i]]) p[i]++; 70 if (i+p[i]>id+p[id]) id=i; 71 ans=(ans-(p[i]>>1)+mod)%mod; 72 } 73 printf("%d\n",ans); 74 return 0; 75 }
BZOJ3160: 萬徑人蹤滅