hihocoder#1239 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  (微软2016年秋招第三题)

输入

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

分析:

题意就是找到给定序列中斐波那契子序列的个数。

1. 首先想到的就是动态规划,dp[i]表示以i结尾的斐波那契子序列,然后每次变量j (0...i-1)更新i。

但是这样时间复杂度是O(n^2),数据量10^6,肯定是超时的。

2. 考虑优化,每次更新只与斐波那契数列中的元素结尾的有关,没必要dp开那么大,并且从头遍历。

所以可以把dp存成vector<pair<int,int>>,一个表示值,一个表示以此结尾的fib序列个数。然后每次变量vector即可。

但是很遗憾,还是超时了。。。(当数组中斐波那契数列中的数存在很多时,依然是个O(n^2))。

3. 继续优化,其实每个遍历到每个数在斐波那契序列中,更新结果时,只与其在斐波那契序列中前一个数结尾fib序列个数有关。

所以可以把dp[i]考虑存储为以fib[i]结尾的斐波那契子序列个数,100000以内斐波那契数只有25个,所以时间复杂度O(25n) = O(n),就可以了。

注意: 用long long存result防止溢出;记得mod 1000000007

代码:

 1 #include<iostream>
 2 #include<unordered_map>
 3 using namespace std;
 4 int fib[26];
 5 const int m = 1000000007;
 6 void init() {
 7     int a = 1, b = 1, c = 2;
 8     fib[1] = 1;
 9     fib[2] = 1;
10     for (int i = 3; i <= 25; ++i) {
11         c = a + b;
12         fib[i] = c;
13         a = b;
14         b = c;
15     }
16 }
17 int findPos(int x) {
18     for (int i = 1; i <= 25; ++i) {
19         if (fib[i] == x) {
20             return i;
21         }
22     }
23     return -1;
24 }
25
26 int n;
27 int nums[1000000];
28 long long dp[26] = {0};
29 int main() {
30     init();
31     cin >> n;
32     long long result = 0;
33     for (int i = 0; i < n; ++i) {
34         cin >> nums[i];
35     }
36     int first = -1, second = -1;
37     for (int i = 0; i < n; ++i) {
38         if (nums[i] == 1) {
39             first = i;
40             for (int j = i + 1; j < n; ++j) {
41                 if (nums[j] == 1) {
42                     second = j;
43                     break;
44                 }
45             }
46             break;
47         }
48     }
49     if (first != -1) {
50         dp[1] = 1;
51         result += 1;
52     }
53     if (second != -1) {
54         dp[2] = 1;
55         dp[1] ++;
56         result += 2;
57     }
58     if (second == -1) {
59         cout << result << endl;
60         return 0;
61     }
62
63     for (int i = second + 1; i < n; ++i) {
64         if (findPos(nums[i]) == -1 ) {
65             continue;
66         }
67         if (nums[i] == 1) {  //1单独处理
68             dp[2] += dp[1];
69             dp[1]++;
70             result += dp[1];
71             dp[2] %= m;
72             result %= m;
73             continue;
74         }
75         dp[findPos(nums[i])] += dp[findPos(nums[i]) - 1];
76         result += dp[findPos(nums[i]) - 1];
77         dp[findPos(nums[i])] %= m;
78         result %= m;
79     }
80     cout << result << endl;
81 }
时间: 2024-10-24 21:57:36

hihocoder#1239 Fibonacci的相关文章

(dp)hihocoder - 1239 Fibonacci

原题链接:http://hihocoder.com/problemset/problem/1239 题意:给一个数列,求构成斐波那契数列的子序列有几个. 分析:我们可以在统计的过程中动态加出结果. 由于有两个1,我们需要进行一些区分,我们首先定义m[0]表示以第一个1为结尾的斐波那契数列的个数,m[1]表示以第二个1为结尾的斐波那契数列的个数,同理,m[i](i>1,i表示斐波那契数的编号)表示以Fibonacci(i)为结尾的斐波那契数列的个数. 比如这个例子1 1 2 1 2 3 4 5 .

NYOJ 480 Fibonacci Again!

Fibonacci Again! 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描写叙述 求第n个斐波那契数是否是一个素数,n为整数 f[n]=f[n-1]+f[n-2] (2<n<30) f[1]=3,f[2]=7 输入 输入整数m,0<m<30,输入-1表示结束输入 输出 假设f[m]是素数 则输出Yes,否则输出No, 每行输出占一行. 例子输入 2 3 例子输出 Yes No #include<stdio.h> int f[35]={0

HDU1848 Fibonacci again and again

Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8198    Accepted Submission(s): 3412 Problem Description 任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的:F(1)=1;F(2)=2;

[hihoCoder#1381]Little Y&#39;s Tree

[hihoCoder#1381]Little Y's Tree 试题描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每次小J会删掉这个树中的k条边,这棵树被分成k+1个连通块.小J想知道每个连通块中最远点对距离的和. 这里的询问是互相独立的,即每次都是在小Y的原树上进行操作. 输入 第一行一个整数n,接下来n-1行每行三个整数u,v,w,其中第i行表示第i条边边权为wi,连接了ui,vi两点. 接下来一行一个整数q,表示有q组询问. 对于每组询问,第一行一个正整数k,接下来一

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hdu 5167 Fibonacci(DFS)

hdu 5167 Fibonacci 问题描述 斐波那契数列的递归定义如下: Fi=???01Fi?1+Fi?2i = 0i = 1i > 1 现在我们需要判断一个数是否能表示为斐波那契数列中的数的乘积. 输入描述 有多组数据,第一行为数据组数T(T≤100,000). 对于每组数据有一个整数n,表示要判断的数字. 0≤n≤1,000,000,000 输出描述 对于每组数据,如果可以输出"Yes",否则输出"No". 输入样例 3 4 17 233 输出样例

HDU 4099 Revenge of Fibonacci

Revenge of Fibonacci Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 204800/204800 K (Java/Others) Total Submission(s): 2027    Accepted Submission(s): 475 Problem Description The well-known Fibonacci sequence is defined as following: Here w

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46

HUDJ 1021 Fibonacci Again

Fibonacci Again Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 36028    Accepted Submission(s): 17385 Problem Description There are another kind of Fibonacci numbers: F(0) = 7, F(1) = 11, F(n)