Project Euler Problem 57

 

Project Euler Problem 57

 

 

这个要深入研究一下。。。。我是暴力写的。。太对不起人了。。。以后再改。。。

最近也在看连分数。。但是还是太囧。。

下面是在论坛讨论上大家的讨论。。以后再整理。。感觉还是遇到大牛了。。。。

 

 

巨牛的一个人用汇编写的代码,这个让我意识到,你真的很强悍!!

 

.data?

    sumof       dd    ?

    cword       dw    ?

 

.code

 

start:

    mov   ecx,1000       ;loop counter

    finit

    fstcw cword          ;get control word

    or    cword,0c00h    ;adjust it for truncating

    fldcw cword          ;modify FPU accordingly

    fld1

    fld1                 ;initialize 2 registers

start1:

    fadd  st,st(1)

     <script src="http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js" type="text/javascript"></script> <script src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js" type="text/javascript"></script> fadd  st(1),st       ;expand the 2 numbers

    fxch                 ;larger one in top register

    fldlg2

    fld   st(2)

    fyl2x                ;get log of smaller number

    frndint              ;keep only the mantissa

    fldlg2

    fld   st(2)

    fyl2x                ;get log of larger number

    frndint

    fcomip st,st(1)      ;compare the 2 mantissas

    fstp  st

    jz    @F

    inc   sumof          ;increment if not the same

  @@:

    dec   ecx

    jnz   start1

;final result is in "sumof"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

05 Sep 2005 05:53 pm  

KermitDFrog   (Pencil/Paper)   

 

if you examine the function: 

 

Len(Numerator)/Len(Denominator) 

 

you'll notice a pattern. 

 

1 <= x < 2 

 

 

x,1,1,1,1,1,1,1,x,1,1,1,1,x,1,1,1,1,1,1,1,x... 

 

that is, an x (the value with different Len values. except in the first case of 1.) followed by 7 ones, x, then 4 

 

ones, then x. 

 

so, if we measure the distances between x's, we get 8, and 5, (thats measured x to x. as follows: 

 

x, 1, 1, 1, 1, 1, 1, 1, x, 1, 1, 1, 1, x... 

0, 1, 2, 3, 4, 5, 6, 7, 8, 

0, 1, 2, 3, 4, 5... 

 

so the First answer you should generate out of this is: 

;this is just psuedocode. 

 

Loop While i <= Limit [ 

i += 8 

i += 5 

x += 2 

 

So, this can be easily simplified to 

 

Loop While i <= Limit [ 

i += 13 

x += 2 

 

further, you can break this down to 

 

2*((Limit-1) / 13) 

 

that is, x += 2 becomes 2* 

Limit is the upper limit of the function (1000 in this case) 

you subtract one to eliminate the first x (which equals 1, and is therefore an exception to the pattern.) and 

 

divide by 13, which is the distance between pairs of x's. 

 

So, the number of non-1 values the function 

 

Len(N)/Len(D), where the Limit Value is 1000, is the following. 

 

2*(1000-1/13) 

2*(999/13) 

1998/13 

153.692 

 

the function has a minor margin of error, so for relatively small Limit-values, you should be accurate enough to 

 

just take the integer part, which i did, and, apparently, became the first person to post a non-bruteforce method 

 

to solve this problem. 

 

 

Rockin. 

 

 

 

PS, this officially puts me as more than 1/4 done. 13/50's of the way done, to be exact. 

 

 

 

; Edit 

 

This is a better Formula, eliminates the Int(n) portion. Simple Mod Trick. 

 

 

{[2((Limit-1)-((Limit-1) Mod 13))]/13} + 1 

 

 

They should install MathTex or LaTeX on this forum, so I can spew my genius in the appropriate form. 

 

 

 

I believe the magic number in there (the +1) accounts for the first x in the series-- Not entirely sure, can't 

 

prove anything yet.. 

 

 

Ribbet. 

 

 

 

 

 

11 Sep 2005 07:53 am  

KermitDFrog   (Pencil/Paper)   

 

Just a Quick update, The Cleanest Method I came up with uses Mathematica's Floor Function, It looks something 

 

like: 

 

 

(2*Floor[(L-1)/13])+ 1 

 

Although, I'm convinced there is a prettier way of doing this. That doesn't involve that ugly floor function. 

 

~~joe 

 

PS, how are you coming with your better way, Zron? 

 

 

 

 

 

 

 

 

Letting N(n) and D(n) represent the nth numerator and denominator, we have the recurrence relations 

 

N(0) = 1, N(1) = 1, N(n) = 2*N(n-1)+ N(n-2) for n>=2 

D(0) = 0, D(1) = 1, D(n) = 2*D(n-1)+ D(n-2) for n>=2 

 

These are linear, homogeneous recurrence relations, relatively easily solvable by standard methods. (Try a 

 

solution of the form a(n) = r^n, you'll get a quadratic equation for r, with roots r1 and r2, and the final 

 

solution will be a linear combination a(n) = A*r1^n + B*r2^n, where A and B are determined by the initial 

 

conditions.) 

 

In this case, r1=1+sqrt(2) and r2=1-sqrt(2), and 

N(n) = (r1^n + r2^n)/(2) 

D(n) = (r1^n - r2^n)/(2*sqrt(2)) 

 

In fact, I've actually set it so that when the above formula starts with n=2, it coincides with the first 

 

numerator & denominator given in the problem. 

 

Using the formula that the number of digits of x is 1+floor(log10(x)), we see that 

 

numer_dig = 1+floor(log10(N(n))) = 1+floor(n*log10(r1) + log10(1+(r2/r1)^n) - log10(2)) 

denom_dig = 1+floor(log10(D(n))) = 1+floor(n*log10(r1) + log10(1-(r2/r1)^n) - 1.5*log10(2)) 

 

 

[hide code]

#include <stdio.h>

#include <math.h>

 

int main(void)

{

int n, count;

double c1, c2, power, numer_dig, denom_dig;

 

c1 = log10(1.0+sqrt(2.0));

c2 = 2.0*sqrt(2.0)-3.0;

 

count=0; 

for (n=2; n<=1001; n++) {

power = pow(c2,n);

numer_dig = 1 + floor(n*c1 + log10(1+power) -1.0*log10(2.0));

denom_dig = 1 + floor(n*c1 + log10(1-power) -1.5*log10(2.0));

if (numer_dig >denom_dig) count++;

}

printf("count=%d/n", count);

return 0;

}

 

 

 

 

 

 

 

 

 

31 Jan 2008 04:35 pm  

observ   (C/C++)   

 

Using the recurrences 

 

nr = 2dr-1 + nr-1 [0] 

dr = dr-1 + nr-1 [1] 

=> nr = dr + dr-1 [2] 

 

I end up with 

 

 

[hide code]

#include <iostream>

#include <iomanip>

#include <gmpxx.h>

 

int main ()

{

    mpz_class n (1393), d (985), powerten (1000);

    int sn = 7, count = 0;

    do

    {

do

{

   if (n >= powerten)

++count;

   mpz_class old_d (d);

   d = n + d;

   n = d + old_d;

} while (++sn < 1000 && d < powerten);

powerten *= 10;

    } while (sn < 1000);

    std::cout << "Answer: " << count << std::endl;

    return 0;

}

 

amitg@athena. time ./p57 

Answer: 153 

./p57 0.00s user 0.00s system 154% cpu 0.003 total 

 

Incidentally, we can derive a pure recurrence for the denominator (not involving the numerator): 

 

nr-1 + dr-1 = dr [3] (from 1) 

nr-1 - dr-1 = dr-2 [4] (from 2) 

 

Subtracting 4 from 3: 

 

2dr-1 = dr - dr-2 

=> dr = 2dr-1 + dr-2 [5] 

 

Now, given that n1 = 3 and d1 = 2, we get (from 1 and 2): 

 

2n0 + d0 = 3 

n0 + d0 = 2 

 

We get n0 = d0 = 1. 

 

This makes 5 the Pell Number recurrence (see http://mathworld.wolfram.com/PellNumber.html), with values 1, 2, 5, 

 

12, 29, ... 

 

Similarly, we can derive a recurrence relation only in n for the numerator: 

 

2dr-1 = nr - nr-1 (from 0) 

2dr = 2dr-1 + 2nr-1 (from 1) 

 

=> nr+1 - nr = nr - nr-1 + 2nr-1 

=> nr+1 = 2nr + nr-1 

=> nr = 2nr-1 + nr-2 [6] 

 

This is the same recurrence relation as the denominator, but with different seed values, so it does not generate 

 

Pell numbers. 

 

I found it easier to use the mutually dependent recurrences, however.  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值