题目大意:给定一个数字序列,求该序列的所有子序列中有多少是斐波拉契数列的前缀,即满足"1 1 2 3 ..."的形式。
解题思路:首先注意ai的范围,首先可以肯定斐波拉切数列不会太多,最多25个。那么可以利用动态规划的思想,dp[i][j]表示前i个串当中,以斐波拉切数列中的第j数个结尾的,有多少种。
那么可以很简单的得到状态转移方程:
IF a[i] = fib[j]
dp[i][j] = dp[i-1][j] + dp[i-1][j-1];
ELSE
dp[i][j] = dp[i-1][j]
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1000005;
const int mod = 1e9+7;
int n,a[maxn],dp[maxn][30];
int fib[100005];
void init()
{
fib[1] = fib[2] = 1;
for(int i = 3; i <= 25; i++)
fib[i] = fib[i-1] + fib[i-2];
}
int main()
{
init();
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
for(int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
if(a[i] == 1)
dp[i][1] = (dp[i-1][1] + 1) % mod;
else dp[i][1] = dp[i-1][1];
}
for(int i = 1; i <= n; i++)
for(int j = 2; j <= 25; j++)
{
if(a[i] == fib[j])
dp[i][j] = (dp[i-1][j] + dp[i-1][j-1]) % mod;
else dp[i][j] = dp[i-1][j];
}
int ans = 0;
for(int i = 1; i <= 25; i++)
ans = (ans + dp[n][i]) % mod;
printf("%d\n",ans);
}
return 0;
}