Java 更有效的解决方案:Project Euler#2:偶数斐波那契数
问题: 斐波那契序列中的每个新项都是通过添加 前两届 从1和2开始,前10个术语将 是:Java 更有效的解决方案:Project Euler#2:偶数斐波那契数,java,algorithm,Java,Algorithm,问题: 斐波那契序列中的每个新项都是通过添加 前两届 从1和2开始,前10个术语将 是: 1,2,3,5,8,13,21,34,55,89,… 通过考虑Fibonacci序列中的项,其值不 超过四百万,求偶数项之和 我的代码:(很好用) 我正在寻找一个更有效的算法来解决这个问题。有什么提示吗?你不能再改进了,你所做的任何改进都可以忽略不计,而且取决于你运行的操作系统 示例: 在我的Mac上以循环方式运行代码1M次73-75毫秒(运行了几次)。 更改条件: if(newFib % 2 == 0){
1,2,3,5,8,13,21,34,55,89,…
通过考虑Fibonacci序列中的项,其值不
超过四百万,求偶数项之和
我的代码:(很好用)
我正在寻找一个更有效的算法来解决这个问题。有什么提示吗?你不能再改进了,你所做的任何改进都可以忽略不计,而且取决于你运行的操作系统 示例:
在我的Mac上以循环方式运行代码1M次73-75毫秒(运行了几次)。
更改条件:
if(newFib % 2 == 0){
致:
再运行几次,我得到51-54毫秒
- 如果你要在不同的操作系统上运行相同的东西,你可能(和 可能会)得到不同的结果 即使我们将上述考虑作为一种改进,在1M中分为20MS,对于单次运行来说,“改进”是没有意义的(20纳米)。李>
(1,1,2)
(3,5,8)
(13,21,34)
给定(a,b,c)
这是(b+c,b+2*c,2*b+3*c)
这意味着我们只需要存储最后两个数字,并计算给定的(a,b)
,(a+2*b,2*a+3*b)
因此,(1,2)->(5,8)->(21,34)->……
并始终返回最后一个
这将比“过滤器”方法工作得更快,因为它使用if语句,从而减少了管道
生成的代码是:
int b = 1;
int c = 2, d;
long sum = 0;
while(c < 4000000) {
sum += c;
d = b+(c<<0x01);
c = d+b+c;
b = d;
}
System.out.println(sum);
intb=1;
int c=2,d;
长和=0;
而(c<4000000){
总和+=c;
正如我在评论中提到的,实际上没有必要进一步改进。
我做了一些测量
- 循环了100万次
- 以[ms]为单位测量时间
- ms/1000000=ns
- 因此单次通过时间[ns]如下:
- [176 ns]-利用偶数每三分之一
- [179 ns]-&1而不是%2
- [169 ns]-&1而不是%2,如果通过-,^,&
[edit1]新代码
- [105 ns]-利用每三分之一个偶数+衍生的fibonaci双迭代
[edit2]新代码
- [76 ns]-减少操作数计数以降低开销和堆损坏
- 最后一个显然在我的机器上获胜(尽管我希望第一个会是最好的)
- 所有测试均在Win7 x64 AMD A8-5500 3.2GHz上进行
- 无线程应用程序32位编译器BDS2006 Trubo C++
- 答案中已经很好地提到了1,2,所以我只评论了3:
s+=a&(-((a^1)&1));
- (a^1)否定最爱的位
- ((a^1)和1)为1表示偶数,为0表示奇数a
- -((a^1)和1))是-1表示偶数,0表示奇数a
- -1是0xFFFFFF,因此通过它对数字进行anding不会改变它
- 0是0x00000000,因此它的AND数将是0
- 因此,如果
- 你也可以用否定代替异或,但是在我的机器上速度要慢得多
好的,这是代码(如果您想自己编写代码,请不要进一步阅读):
//---------------------------------------------------------------------------
int euler002()
{
//斐波那契序列中的每个新项都是通过将前两项相加生成的。
//从1和2开始,前10个术语将是:1、2、3、5、8、13、21、34、55、89。。。
//通过考虑Fibonacci序列中值不超过400万的项,求偶数值项之和。
int a,a0=0,a1=1,s=0,N=4000000;
/*
//1.[176纳秒]
a=a0+a1;a0=a1;a1=a;//奇数
a=a0+a1;a0=a1;a1=a;//偶数
对于(;a=N)断裂;
如果((a&1)=0)s+=a;
}
//3.[169纳秒]
对于(;;)
{
a=a0+a1;a0=a1;a1=a;
如果(a>=N)中断;
s+=a&(((a^1&1));
}
//4.[105 ns]/[edit1]
a0+=a1;a1+=a0;a=a1;//2x
对于(;a假设连续斐波那契数
a, b,
c = a + b,
d = a + 2b,
e = 2a + 3b,
f = 3a + 5b,
g = 5a + 8b = a + 4(a + 2b) = a + 4d,
使用
ef0=0,ef1=2,efn=efn-2+4 efn-1项目Euler问题2的答案是(用Java):
intx=0;
int y=1;
intz=x+y;
int-sumeen=0;
而(z<4000000){
x=y;
y=z;
z=x+y;
如果(z%2==0){
sumeen+=z;///或sumeen=sumeen+z
}
}
System.out.printf(“偶数值项之和:%d\n”,sumeven);
这是最简单的答案。F(n)是第n个Fibonnaci数,即F(n)=F(n-1)+F(n-2)
假设F(n)是偶数,那么
F(n)=F(n-1)+F(n-2)=F(n-2)+F(n-3)+F(n-2)
F(n)=2F(n-2)+F(n-3)
--这证明了每三项都是偶数(如果F(n-3)是偶数,那么F(n)也必须是偶数)
F(n)=2[F(n-3)+F(n-4)]+F(n-3)
=3F(n-3)+2F(n-4)
=3F(n-3)+2F(n-5)+2F(n-6)
根据公式1:
F(n-3)=2F(n-5)+F(n-6)
2F(n-5)=F(n-3)-F(n-6)
F(n)=3F(n-3)+[F(n-3)-F(n-6)]+2F(n-6)
=4F(n-3)+F(n-6)
如果偶数序列由每三个数组成(n,n-3,n-6,…)
偶数斐波那契序列:
E(k)=4E(k-1)+E(k-2)
Fib序列F={0,1,1,2,3,5,8…}
偶Fib序列E={0,2,8,…}
代码:
public static long findEvenFibSum(long n){
long term1=0;
long term2=2;
long curr=0;
long sum=term1+term2;
while((curr=(4*term2+term1))<=n){
sum+=curr;
term1=term2;
term2=curr;
}
return sum;
}
公共静态长findevinfibsum(长n){
长期1=0;
长期2=2;
长电流=0;
长和=第1项+第2项;
wh
//---------------------------------------------------------------------------
int euler002()
{
// Each new term in the Fibonacci sequence is generated by adding the previous two terms.
// By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
// By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
int a,a0=0,a1=1,s=0,N=4000000;
/*
//1. [176 ns]
a=a0+a1; a0=a1; a1=a; // odd
a=a0+a1; a0=a1; a1=a; // even
for (;a<N;)
{
s+=a;
a=a0+a1; a0=a1; a1=a; // odd
a=a0+a1; a0=a1; a1=a; // odd
a=a0+a1; a0=a1; a1=a; // even
}
//2. [179 ns]
for (;;)
{
a=a0+a1; a0=a1; a1=a;
if (a>=N) break;
if ((a&1)==0) s+=a;
}
//3. [169 ns]
for (;;)
{
a=a0+a1; a0=a1; a1=a;
if (a>=N) break;
s+=a&(-((a^1)&1));
}
//4. [105 ns] // [edit1]
a0+=a1; a1+=a0; a=a1; // 2x
for (;a<N;)
{
s+=a; a0+=a1; a1+=a0; // 2x
a=a0+a1; a0=a1; a1=a; // 1x
}
*/
//5. [76 ns] //[ edit2]
a0+=a1; a1+=a0; // 2x
for (;a1<N;)
{
s+=a1; a0+=a1; a1+=a0; // 2x
a=a0; a0=a1; a1+=a; // 1x
}
return s;
}
//---------------------------------------------------------------------------
a, b,
c = a + b,
d = a + 2b,
e = 2a + 3b,
f = 3a + 5b,
g = 5a + 8b = a + 4(a + 2b) = a + 4d,
int x = 0;
int y = 1;
int z = x + y;
int sumeven = 0;
while(z < 4000000){
x = y;
y = z;
z = x + y;
if(z % 2 == 0){
sumeven += z; /// OR sumeven = sumeven + z
}
}
System.out.printf("sum of the even-valued terms: %d \n", sumeven);
public static long findEvenFibSum(long n){
long term1=0;
long term2=2;
long curr=0;
long sum=term1+term2;
while((curr=(4*term2+term1))<=n){
sum+=curr;
term1=term2;
term2=curr;
}
return sum;
}
34 = 4*8 + 2,
144 = 34*4 + 8,
610 = 144*4 + 34;
Even(n)=4*Even(n-1)+E(n-2);
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
long n = in.nextLong();
long a=2;
long b=8;
long c=0;
long sum=10;
while(b<n)
{
sum +=c;
c=b*4+a;
a=b;
b=c;
}
System.out.println(sum);
}
}