hihocoder: 1239 Fibonacci(微软2016校园招聘9月在线笔试)

题目链接:

传送门

题意:

给定一个长度为n的序列然后判断这个序列有多少个子序列是Fibonacci数列的前缀。

分析:

简单的dp,因为a[i]<100000,因此Fibonacci数列最多有30项。设 dp[i][j] 表示到第i个数为止含有Fibonacci数列的前缀长度为j的有多少种。
转移分为两种:

  • a[i]=1 :

    • dp[i][0]=d[i1][0]+1,dp[i][1]=dp[i1][1]+dp[i1][0];
  • a[i]1anda[i]=Fibonacci[j] :

    • dp[i][j]=dp[i1][j]+dp[i1][j1];

Code

#include 

using namespace std;

const int maxn = 1e6+10;

typedef long long LL;

const LL mod = 1e9+7;

LL dp[maxn][30];

int a[maxn];

int fib[30];

void init(){
    fib[0]=1;
    fib[1]=1;
    for(int i=2;i<30;i++){
        fib[i]=fib[i-1]+fib[i-2];
    }
}

int main()
{
    init();
    int n;
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        for(int i=0;i<30;i++)
            dp[0][i]=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<30;j++)
                dp[i][j]=dp[i-1][j];
            int pos = lower_bound(fib,fib+30,a[i])-fib;
            if(fib[pos]==a[i]){
                if(fib[pos]==1){
                    dp[i][pos+1]=(dp[i][pos+1]+dp[i-1][0])%mod;
                    dp[i][pos]=(dp[i][pos]+1)%mod;
                }
                else{
                    dp[i][pos]=(dp[i][pos]+dp[i-1][pos-1])%mod;
                }
            }
        }
        LL ans = 0;
        for(int i=0;i<26;i++){
            ans = (ans+dp[n][i])%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(DP,剑指Offer)