首页 > 代码库 > bzoj 3978: [WF2012]Fibonacci Words

bzoj 3978: [WF2012]Fibonacci Words

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