1. 程式人生 > >bzoj 3978: [WF2012]Fibonacci Words

bzoj 3978: [WF2012]Fibonacci Words

case 字符串 logs == 包含 出現的次數 print 一個 ret

Description

斐波那契01字符串的定義如下 F(n) = { 0 if n = 0 1 if n = 1 F(n-1)+F(n-2) if n >= 2 } 這裏+的定義是字符串的連接。F(n)的前幾個元素如下: F(0)=0 F(1)=1 F(2)=10 F(3)=101 F(4)=10110 F(5)=10110101 F(6)=1011010110110 F(7)=101101011011010110101 F(8)=1011010110110101101011011010110110 F(9)=1011010110110101101011011010110110101101011011010110101 給定一個模式串p和一個數n,p在F(n)中出現了多少次?

Input

每個測試點包含多組測試數據。 每組測試數據的第一行包含一個正整數n。第二行包含模式串p。

Output

對於每個測試數據,輸出測試數據編號和p在F(n)出現的次數。出現的位置可能會重疊。 遞歸求出詢問串在F(i)中的出現次數 f[i]=f[i-1]+f[i-2]+(F(i-1)與F(i-2)的交界上的出現次數)
#include<bits/stdc++.h>
int n;
char s[100007],Fl[107][100007],Fr[107][100007];
int ls[107],ks=0;
long long f[107];
int main(){
    Fl[
0][0]=Fr[0][0]=0; Fl[1][0]=Fr[1][0]=1; ls[0]=ls[1]=1; for(int i=2;i<=100;++i){ ls[i]=ls[i-1]+ls[i-2]; if(ls[i]>100000)ls[i]=100000; for(int j=0;j<ls[i];++j){ Fl[i][j]=(j<ls[i-1]?Fl[i-1][j]:Fl[i-2][j-ls[i-1]]); Fr[i][j]=(j<ls[i-2]?Fr[i-2
][j]:Fr[i-1][j-ls[i-2]]); } } while(scanf("%d",&n)==1){ scanf("%s",s); int len=strlen(s); f[0]=f[1]=0; if(len==1)f[s[0]-0]=1; for(int i=2;i<=n;++i){ f[i]=f[i-1]+f[i-2]; for(int j=1;j<len;++j)if(j<=ls[i-1]&&len-j<=ls[i-2]){ for(int k=0;k<len;++k)if(s[k]!=(k<j?Fr[i-1][j-1-k]:Fl[i-2][k-j]))goto o; ++f[i]; o:; } } printf("Case %d: %lld\n",++ks,f[n]); } return 0; }

bzoj 3978: [WF2012]Fibonacci Words