求勾股数

基本概念

众所周知(3,4,5)和(6,8,10)是两组勾股数,区别是前一组三个数的公因数是一而后一组的不是。像第一组勾股数一样三个数之间两两互质的就叫做 本原勾股数。而且将一组本原勾股数里的三个数同时扩大相同的倍数得到的一组数还是勾股数(只不过不是本原勾股数)。所以我们找勾股数时只用找本原勾股数就行了。

本原勾股数的性质

  1. 本原勾股数里的三个数两两互质。
  2. 将一组本原勾股数里的三个数同时扩大相同的倍数得到的一组数还是勾股数。
  3. 对于满足 \(a^2 + b^2 = c^2\) 的一组本原勾股数,\(a\)\(b\) 必须是一奇一偶。
  4. 本原勾股数的标准形式为:(\(m^2 - b^2\)\(2mn\)\(m^2 - n^2\)),其中 \(n < m\) 且互质,并且还是一奇一偶(满足性质3)。

性质 3 的证明

首先对于满足 \(a^2 + b^2 = c^2\) 的一组本原勾股数,三个数不可能同时是偶数(不满足两两互质的定义),不可能同时是奇数(不满足勾股定理),不可能是两偶一奇(不满足勾股定理),所以只可能是一偶两奇。若 \(c\) 是偶数,则偶数的平方模 4 为 0,而两个奇数的平方和模 4 是 2,明显不满足勾股定理,所以只能是\(a\)\(b\) 一奇一偶且 \(c\) 是奇数。

性质 4 的推导

推导

实现

// 以 c 索引
std::vector<std::array<int, 2>> R[MXR + 5];
void solve()
{
    for (int i = 1; i * i <= MXR; i++) {
        for (int j = 1; j < i && i * i + j * j <= MXR; j++) {
            if ((i + j) % 2 == 0 || std::__gcd(i, j) != 1) {
                continue;
            }

            int a = 2 * i * j;
            int b = i * i - j * j;
            int c = i * i + j * j;
            for (int k = 1; c * k <= MXR; k++) {
                R[c * k].push_back({ a * k, b * k });
            }
        }
    }
}
posted @ 2025-02-14 20:19  Young_Cloud  阅读(209)  评论(0)    收藏  举报