微软2016校园招聘9月在线笔试C.Fibonacci

#1239 : Fibonacci

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

Given a sequence {an}, how many non-empty sub-sequence of it is a prefix of fibonacci sequence.

A sub-sequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.

The fibonacci sequence is defined as below:

F1 = 1, F2 = 1

Fn = Fn-1 + Fn-2, n>=3

输入

One line with an integer n.

Second line with n integers, indicating the sequence {an}.

For 30% of the data, n<=10.

For 60% of the data, n<=1000.

For 100% of the data, n<=1000000, 0<=ai<=100000.

输出

One line with an integer, indicating the answer modulo 1,000,000,007.

样例提示

The 7 sub-sequences are:

{a2}

{a3}

{a2, a3}

{a2, a3, a4}

{a2, a3, a5}

{a2, a3, a4, a6}

{a2, a3, a5, a6}


样例输入
6
2 1 1 2 2 3
样例输出
7

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

还是太弱了,一开始以为是个组合数学题。后来看了别人的代码才知道是dp

要得到长度为i的Fibonacci数列的前缀,前面必有i-1的Fibonacci数列的前缀

dp[j][i]表示到i个数为止长度为j的Fibonacci数列的前缀有多少个


状态转移方程 dp[j][i]=dp[j][i-1]+dp[j-1][i-1];(a[i]>1, i表示第i个Fibonacci数列=a[i])

dp[1][i]=dp[1][i-1]+1; dp[2][i]= dp[1][i-1]+d[2][i-1](a[i]=1)


#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
using namespace std;

const int N = 30;
const int M = 1000001;
const int mod = 1000000007;
long long dp[N][M];
int a[M];
map
       
       
         g; void debug(int n) { for(int i = 0; i < 30; i++) printf("%d ", dp[i][n]); printf("\n"); } int main(void) { int n; int i, j; g[1] = 2; a[1] = a[2] = 1; for(i = 3; i < 30; i++) { a[i] = a[i-1] + a[i-2]; g[a[i]] = i; } while(~scanf("%d", &n)) { memset(dp, 0, sizeof(dp)); for(i = 1; i <= n; i++) scanf("%d", &a[i]); for(i = 1; i <= n; i++) { for(j = 1; j < 30; j++) dp[j][i] = dp[j][i-1]; int tmp = g[ a[i] ]; if(!tmp) continue; if(tmp == 2) { dp[1][i] = (dp[1][i] + 1)%mod; dp[2][i] = (dp[2][i] + dp[1][i-1])%mod; } else { dp[tmp][i] = (dp[tmp][i] + dp[tmp-1][i])%mod; } // printf("tmp=%d\n", tmp); // debug(i); } long long ans = 0; for(i = 1; i < 30; i++) ans = (ans + dp[i][n])%mod; printf("%lld\n", ans); } return 0; } 
       
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值