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
",++ks,f[n]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/7122909.html