我正在解决这个问题:
G(n) is defined as G(n) = G(n-1) + f(4n-1) , for n > 0 and G(0) = 0 f(i) is ith Fibonacci number. Given n you need to evaluate G(n)
modulo 1000000007。
Input First line contains number of test cases t (t<40000). Each of the next t
行包含整数n(0 <= n <0。 2 ^ 51)。
Output For each test case print G(n) modulo 1000000007. Example Input: 2 2 4 Output: 15 714
这是我写的代码:
typedef long long type;
#define check 1000000007
type x;
type y;
type f(type n)
{
return(ceil((pow(1.618,n) - pow(-0.618,n))/((sqrt(5)*1.0))));
}
type val(type n)
{
if(n==0)
return 0;
else
return (val(n-1)+f(4*n-1));
}
int main()
{
cin>>x;
while(x--)
{
cin>>y;
cout<<val(y)%check<<endl;
}
//getch();
return 0;
}
你能建议任何改进吗?
答案 0 :(得分:1)
有时这些问题可以通过数学技巧解决,
而不是暴力解决方案。
在我看来,n
和模数的大值表明了
存在一个聪明的解决方案。当然,找出解决方案是困难的部分。
(我不确定这在你的情况下是否理想,我只是指向你另一种方式)
例如,在Art of Computer Programming, Volume 1: Fundamental Algorithms中 Knuth使用“生成函数”,这是一种构造封闭形式的聪明方法 对于Fn斐波纳契数。
有关详细信息,请参阅Generating Functions (pdf)
为什么要关心 生成序列的函数? 有几个答案,但现在是 一:如果我们能找到一个产生 一个序列的功能,然后我们可以 经常为第n个发现一个封闭的形式 系数 - 这可能很漂亮 有用!例如,一个封闭的表格 x n 的系数 x /(1-x-x 2 )的幂级数 将是一个明确的公式 第n个斐波纳契数。 [...]
答案 1 :(得分:1)
G(n)= G(n-1)+ f(4n-1)= G(n-2)+ f(4n-1)+ f(4n-5)等。
因此
G(n)= f(4n-1)+ f(4n-5)+ f(4n-9)... f(3)
f(n)= f(n-1)+ f(n-2)= 2f(n-2)+ f(n-3)= 3f(n-3)+ 2f(n-4)= 5f(n-4)+ 3f(n-5) f(n-5)= 3f(n-8)+ 2f(n-9) 从而 f(n)= 5f(n-4)+ 9f(n-8)+ 6f(n-9) = 5f(n-4)+ 9f(n-8)+ 18f(n-12)+ 12f(n-13)
= 5f(n-4)+ 9f(n-8)+ 18f(n-12)+ 36f(n-16)+ 24f(n-17)
在任何情况下都清楚系数每次都会加倍。当然,从上面我们可以用f(n-8)等来定义f(n-4)。不确定这将导致什么。
这里有一个系列,f(3)= 2和f(2)= 1所以最后你会加上常数。
实际上,为了您的目的,您可以在一次通过中计算f(n),而不必在此时存储超过2个,并且当您通过计算f(n)时,您知道上面G的公式当n与每个点的3 mod 4一致时,你可以适当地更新G总和斐波那契数。
你找不到用这么大的数字(2到51的幂)保存一个表的空间,甚至不是磁盘,尽管它实际上是你需要存储在表中的总和(f(3), f(3)+ f(7),f(3)+ f(7)+ f(11)等)如果你要保存任何东西。
答案 2 :(得分:0)
所以f()是斐波那契函数?我建议你使用常规的递归算法。但是你可以通过添加缓存来显着提高性能,因为对于较小的i值的调用会经常重复调用f(i)。
您可以使用静态局部整数数组来完成此操作。如果元素为0则为未命中,因此您计算该值并将其存储在数组中。
这样你就可以避免使用浮点运算而不会填满堆栈。
答案 3 :(得分:0)
我认为获得G(n)
价值的更好方法是计算它:
type val(type n, std::vector<type> &fib)
{
type ret = 0, s = min(type(fib.size()), n);
for(type i=0; i < s; ++i)
ret += fib[i];
if(n > fib.size()){
fib.reserve(n);
int tmp;
for(type i = fib.size(); i < n; ++i){
tmp = f(4*i+3);
fib.push_back(tmp);
ret += tmp;
}
}
return ret;
}
(对于整个代码检查http://www.ideone.com/jorMy)
避免在任何地方递归,这样它就不会计算每次斐波那契函数。
编辑:我花了很多时间才发现(我的数学有点生锈),但你也可以这样写val:
numtype val(numtype n) {
return ceil(2.218*pow(6.8541,n-1) - 0.018*pow(0.145898,n-1) - 0.2);
}
(http://www.ideone.com/H1SYz上的代码)
这是您的总和的封闭形式。如果你想亲自找到它(毕竟是作业),请跟随Nick D回答。