【问题标题】:Project Euler Problem 233欧拉计划问题 233
【发布时间】:2009-03-08 11:29:04
【问题描述】:

我已决定接下来处理 Project Euler problem 233,但我遇到了一些重大问题!我已经做了一些分析并取得了一些相当不错的进展,但我现在陷入了困境。这是我的工作:

引理 1: 由于圆经过 4 个角点,因此任何 n 至少有 4 个解。但是对于圆周上的每个点,通过反射发现了另外 7 个点。所以总有8k+4个格点。

引理 2: 圆的半径为 (√2)n,圆心为 (n/2, n/2),因此其方程为 (x-n/2)^2 + (y-n/2)^2 = [n/√2]^2。这减少到 x^2+y^2 = n(x+y)。

引理 3: 如果 x^2+y^2 = n(x+y) 的解写成 (x, y, z),则另一个解是 (kx, ky, kz)。证明是:

(x+y)n = x^2+y^2

(kx)^2+(ky)^2 = (kx+ky)m
k(x^2+y^2) = (x+y)m
m = kn

这和我的思路一样 - 我看不到从那里去的任何地方,但它被包括在内,因为它可能很有用。

我的下一个想法是移动圆心。将有相同数量的解决方案在任何维度上移动一个整数。所以当n/2为整数时,所以n=2k,x^2+y^2 = 2*k^2。事实证明,这个方程的解与方程 x^2+y^2=k^2 的解一样多(参见 Sloane A046109)。

这也提供了一种通过A046080 计算任意 n 的解数的简单方法。如果 4k+1 形式的 n 中素数的幂是 f[0]...f[m],则解的数量是 4*product(2f[i]+1 | i in [0.. .m])。

这让我可以向后工作:4.product(2f[i]+1 | i in [0...m]) = 420,所以 product(2f[i]+1 | i in [0.. .m]) = 105 = 3*5*7。我能够想出这个程序,我认为它可以找到所有 n 的总和,形式为 2k 且小于 10^11,它有 420 个圆格点。答案(我希望!)是 257199853438240692。

这是 C 程序:

#include "stdlib.h"
#include "stdio.h"
#include "math.h"
#include "string.h"

#define lim 1000000000L

char prime[lim];
long primes[50000000];
long len = 0;

int main(void)
{
    long i, j;
    for(i = 0; i < lim; i++)
    {
        prime[i] = 1;
    }

    for(i = 2; i < lim; i++)
    {
        if(prime[i])
        {
            for(j = 2*i; j < lim; j += i) prime[j] = 0;
            if((i-1)%4 == 0)
            {
                prime[i] = 2;
                //printf("%li\n", i);
                primes[len++] = i;
            }
        }

        if(i < 1000 || (i < 10000 && i%1000 == 0) || i%10000 == 0) printf("%li, %li\n", i, len);
    }

    printf("primes!\n");

    long a, b, c, v, total = 0, k;
    for(a = 0; a < len; a++)
    {
        v = primes[a]*primes[a]*primes[a];
        if(v > 50000000000L) break;

        for(b = 0; b < len; b++)
        {
            if(b == a) continue;

            v = primes[a]*primes[a]*primes[a]*primes[b]*primes[b];
            if(v > 50000000000L) break;

            for(c = 0; c < len; c++)
            {
                if(c == a) continue;
                if(c == b) continue;

                v = primes[a]*primes[a]*primes[a]*primes[b]*primes[b]*primes[c];
                if(v > 50000000000L) break;

                for(k = 1; k*v <= 50000000000L; k++)
                {
                    if(prime[k] == 2) continue;
                    total += k*v;
                }
            }
        }
    }

    for(a = 0; a < len; a++)
    {
        v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a];
        if(v > 50000000000L) break;

        for(b = 0; b < len; b++)
        {
            if(b == a) continue;

            v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[b]*primes[b]*primes[b];
            if(v > 50000000000L) break;

            for(k = 1; k*v <= 50000000000L; k++)
            {
                if(prime[k] == 2) continue;
                total += k*v;
            }
        }
    }

    for(a = 0; a < len; a++)
    {
        v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a];
        if(v > 50000000000L) break;

        for(b = 0; b < len; b++)
        {
            if(b == a) continue;

            v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[b]*primes[b];
            if(v > 50000000000L) break;

            for(k = 1; k*v <= 50000000000L; k++)
            {
                if(prime[k] == 2) continue;
                total += k*v;
            }
        }
    }

    printf("%li\n", 2*total);


    return 0;
}

我们只需要添加具有 420 个圆格点并且形式为 2k+1 的 n 的值!但是,这似乎比 n=2k 更难,而且我看不到任何方法。我也有点不确定我对偶数 n 的回答是否正确,因为该方法非常复杂......有人可以确认吗?有没有一种不用区别对待不同n的简洁方法?

我完全没有想法!


我最感兴趣的是我如何处理 N=2k+1,因为当 N=2k 时,我可以按照 John Feminella 的建议进行操作。

【问题讨论】:

  • 要确认您的答案,请登录 Euler 网站,转到问题 233 并检查您的答案!
  • 我知道,但这只是答案的一部分,所以我无法检查!我没有完整的答案。

标签: algorithm math geometry diophantine


【解决方案1】:

提示 1:圆的半径为 n/√2,对于整数 n,它永远不是整数,因此 A046080 永远不适用。

提示 2:不要费心滑动圆圈。从方格纸上拿起它,想想它,定义它的正方形,以及圆周上未知的兴趣点彼此之间的关系。

提示 3:半圆的内切角始终为 90 度。

提示 4:一个数可以写成两个平方和的多少种方式?

在整个过程中大量使用的奖励提示:symmetry!


剧透警告!


在您尝试根据上述提示解决之前,请不要继续阅读

如果这些提示还不够,以下是与上述提示交错的一些缺失步骤:

提示 1.5:您将不得不改变看待问题的方式,因为您使用的方法是基于有缺陷的前提。

提示 2.5:考虑正方形顶角之间弧线左侧的格点。通过对称,在它的右侧有另一个这样的点,在它的正下方有第三个。关于这些点之间的距离以及它们形成的三角形,你有什么看法?

提示 3.5:对于任何给定的 n,你如何确定在正方形的顶角之间的弧的左侧有多少格点?

【讨论】:

  • 谢谢;我很感激你的回复!恐怕我仍然看不到如何进行。我已经集思广益了很长时间,并认为 (x, y) 点可能存在于一种统一根源的模式中。 IE:一些对之间的关​​系可能是沿圆周的恒定距离。
  • 你已经差不多了。提升一个抽象层次。是一个直角三角形,边角都是格点,斜边的长度是已知的。 不做任何代数,你对另外两条腿的长度有什么看法?
  • BC 不是整数,但 BC^2 是,因为它是两个整数的平方和。事实上,我们知道它是 2*N^2。现在继续提示 3.5 和 4...
  • @PythonPower -- 你需要找到“A”,还是只确定有多少?至于 r() 评论,我不确定你的表达方式(它看起来不像我得到的,虽然它可能是等价的)但是是的,你在正确的轨道上。
  • 没问题。感谢您提出一个比典型的“我不知道如何编码并且我正在使用 .net”问题更深入的问题!
【解决方案2】:

提示 #1。 你的引理 #2 不太正确。你确定那是半径吗?

提示 #2。 答案与平方和函数 r(k, n) 密切相关。这给出了使用 k 个不同的正方形来表示 n 的方法的数量,允许使用零并区分顺序。例如,r(2, 5) 是 8,因为用 2 个正方形表示 5 有 8 种方法:

(-2)^2 + (-1)^2
(-2)^2 + 1^2
2^2    + (-1)^2
2^2    + 1^2
... (and the 4 additional expressions produced by reversing these 2 terms)

可以看到以原点为中心的半径为 p 的圆有 r(2, p^2) 个格点。例如,半径为 5 的圆有:

(-4)^2 + (-3)^2
... and 7 others like this

5^2    + 0^2
(-5)^2 + 0^2
0^2    + 5^2
0^2    + (-5)^2

总共有 12 个。什么样的数字会有 420 个圆格点?现在,如果它们不以原点为中心怎么办?我会让你从这里拿走。

如果你想要一个更大的提示,我已经 rot-13'd (http://rot13.com) 你应该在这里看看:

uggc://zngujbeyq.jbysenz.pbz/FpuvamryfGurberz.ugzy

【讨论】:

  • 感谢您的指点。我仍然看不到如何进行。当中心为 (1/2, 1/2) 时会出现问题......我看不出如何将其转换为易于解决的东西。请问我可以再给点提示吗? :)
【解决方案3】:

您可以参考http://oeis.org/A046109/b046109.txt 来检查最多 1000。我安装了 PARI/GP 并在此处使用了其中一个 PARI 脚本:http://oeis.org/A046109 来检查更高的数字。

【讨论】:

    猜你喜欢
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    相关资源
    最近更新 更多