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
#include
#include
#include
#include
#include
using namespace std;
/*
分析:
用fib记录当前最长斐波那契子序列,则有
fib[0] = 1;
fib[1] = 1;
fib[i] = fib[i-1] + fib[i-2]; (i >=2);
用dp[i]记录子序列最大值为fib[i]时的子序列个数
对于vec[j]( 0<=j<=vec.size()),如果vec[j]在fib里,且索引为i,则有
dp[0] = dp[0] + 1 ( i == 0);
dp[1] = dp[0] + dp[1] ( i == 0 且dp[0] != 0);
dp[i] = dp[i] + dp[i-1] ( dp[i-1] !=0 );
sum = dp[0] + ... length(dp);
该算法的时间复杂度为NloglogM(N为vec的长度,M为最长斐波那契子序列长度),空间复杂度为logM
该算法很容易就能优化到ON的时间复杂度,我们只需要一个hash保存斐波那契数到其位置的映射即可,详细算法请参考FibSequenceEx
*/
int Search(vector const & vec, int val)
{
auto it = lower_bound(vec.begin(), vec.end(), val);
if (it == vec.end())
{
return -1;
}
return it - vec.begin();
}
int FibSequence(vector const & vec)
{
int const mod = 1000000007;
vector fib({ 1, 1, 2 });
vector dp;
dp.resize(fib.size());
long sum = 0;
for (auto&i : vec)
{
if (i == 1)
{
if (dp[0] > 0)
{
sum = (sum + dp[0]) % mod;
dp[1] = (dp[1] + dp[0]) % mod;
}
++dp[0];
++sum;
}
else
{
int iIndex = Search(fib, i);
if (iIndex != -1 && dp[iIndex - 1] != 0)
{
int add = dp[iIndex - 1];
sum = (sum + add) % mod;
dp[iIndex] = (dp[iIndex] + add) % mod;
if (iIndex + 1 == fib.size())
{
fib.push_back(fib[iIndex] + fib[iIndex - 1]);
dp.push_back(0);
}
}
}
}
return sum;
}
/*
通过分析我们可以知道,100000范围内的斐波那契数模59放在59大小的数组里面可以确保每个位置最多只放一个数
*/
int const hash_size = 59;
int GetIndex(vector > const & hash, int val)
{
int i = val % hash_size;
if (hash[i].first == val)
{
return hash[i].second;
}
return -1;
}
int FibSequenceEx(vector const & vec)
{
int const mod = 1000000007;
vector fib({ 1, 1,2 });
vector > hash;
hash.resize(hash_size);
hash[2] = make_pair(2, 2);
vector dp;
dp.resize(fib.size());
long sum = 0;
for (auto&i : vec)
{
if (i == 1)
{
if (dp[0] > 0)
{
sum = (sum + dp[0])%mod;
dp[1] = (dp[1] + dp[0])%mod;
}
++dp[0];
++sum;
}
else
{
int iIndex = GetIndex(hash, i);
if (iIndex != -1 && dp[iIndex -1] !=0)
{
int add = dp[iIndex - 1];
sum = (sum + add) % mod;
dp[iIndex] = (dp[iIndex] + add)%mod;
if (iIndex + 1 == fib.size())
{
int val = fib[iIndex] + fib[iIndex - 1];
hash[val % hash_size] = make_pair(val, fib.size());
fib.push_back(val);
dp.push_back(0);
}
}
}
}
return sum;
}
void GenerateInput(vector &input)
{
int size = 0;
cin >> size;
int val = 0;
for (int i = 0; i < size; ++i)
{
cin >> val;
input.push_back(val);
}
}
void GenerateInputEx(vector &input)
{
vector fib({ 1, 1 });
for (int i = 2; i < 100; ++i)
{
int val = fib[i - 1] + fib[i - 2];
if (val > 100000)
{
break;
}
fib.push_back(val);
}
int n;
for (n = 25; n < 100000; ++n)
{
set setF;
for (size_t i = 1; i < fib.size(); ++i)
{
if (!setF.insert(fib[i] % n).second)
{
break;;
}
}
if (setF.size() == fib.size()-1)
{
break;
}
}
int size = 0;
for (size_t i = 0; i < fib.size(); ++i)
{
for (size_t j = 0; j < 1000000 / fib.size(); ++j)
{
input.push_back(fib[i]);
}
}
}
int main()
{
vector input;
GenerateInputEx(input);
DWORD t1 = ::GetTickCount();
int ret1 = FibSequence(input);
DWORD t2 = ::GetTickCount();
int ret2 = FibSequenceEx(input);
DWORD t3= ::GetTickCount();
cout << ret1 << " " << ret2 << endl;
cout << t2 - t1 << " " << t3 -t2<< endl;
return 0;
}
#include
#include
#include
#include
using namespace std;
/*
通过分析我们可以知道,100000范围内的斐波那契数模59放在59大小的数组里面可以确保每个位置最多只放一个数
*/
int const hash_size = 59;
int GetIndex(vector > const & hash, int val)
{
int i = val % hash_size;
if (hash[i].first == val)
{
return hash[i].second;
}
return -1;
}
int FibSequenceEx(vector const & vec)
{
int const mod = 1000000007;
vector fib({ 1, 1, 2 });
vector > hash;
hash.resize(hash_size);
hash[2] = make_pair(2, 2);
vector dp;
dp.resize(fib.size());
long sum = 0;
for (auto&i : vec)
{
if (i == 1)
{
if (dp[0] > 0)
{
sum = (sum + dp[0]) % mod;
dp[1] = (dp[1] + dp[0]) % mod;
}
++dp[0];
sum = (sum + 1) % mod;
}
else
{
int iIndex = GetIndex(hash, i);
if (iIndex != -1 && dp[iIndex - 1] != 0)
{
int add = dp[iIndex - 1];
sum = (sum + add) % mod;
dp[iIndex] = (dp[iIndex] + add) % mod;
if (iIndex + 1 == fib.size())
{
int val = fib[iIndex] + fib[iIndex - 1];
if (val < 100000)
{
hash[val % hash_size] = make_pair(val, fib.size());
fib.push_back(val);
dp.push_back(0);
}
}
}
}
}
return sum;
}
int main()
{
vector input;
int size = 0;
cin >> size;
int val = 0;
for (int i = 0; i < size; ++i)
{
cin >> val;
input.push_back(val);
}
cout << FibSequenceEx(input) << endl;;
return 0;
}