LOJ6568 「Project Euler 9」特殊勾股数 题解
题目链接:#6568. 「Project Euler 9」特殊勾股数
题意:
一组勾股数由三个自然数组成,$a < b < c$ ,且
例如,$3^2 + 4^2 = 9 + 16 = 25 = 5^2$。
给出 $N$,请输出所有满足 $a + b + c = N$ 的勾股数。
输入格式:
只有一行,一个整数 $N$。
输出格式:
多行,每行三个整数,$a, b, c$ ,表示答案。
数据范围:
对于 $100\%$ 的数据,$N \leq 10^{12}$。
想起上次做的圆上的整点,差点开始异想天开了
考虑一组 $a,b,c$ 是勾股数的充要条件。
不妨设 $a,b < c$ ,$a,b$ 大小关系忽略,且 $\gcd(a,b,c) = 1$ 。
则可以假设 $a$ 为偶数,$b,c$ 为奇数。
因为 $a^2 + b^2 = c^2$ ,若 $c$ 为偶数,则 $a,b$ 均为偶数,与假设不符
若 $c$ 为奇数,则 $a,b$ 中至少有一个为偶数,由乘法的性质易得。
则此时一定存在正整数 $u,v(u > v$ 且 $u,v$ 奇偶性不同 $)$ 使得
证明很简单,直接代入 $a^2 + b^2 = c^2$ 即可。奇偶的话,很显然。
则对于一般的勾股数 $a,b,c$ ,设 $g = \gcd(a,b,c)$ ,则存在唯一表示
则有 $2du(u+v) = N$ 。
因此我们只需要枚举 $\frac{N}{2}$ 的因数 $d$ 和 $u$ (显然 $u$ 也是因数),从而计算出 $v$ 。
则若 $0<v<u \land \gcd(u,v) = 1 \land u,v$ 奇偶性不同
则 $a = 2uvd,~b=(u^2-v^2)d,~c=(u^2+v^2)d$ 就是一组解,输出时注意 $a,b$ 的大小关系
时间复杂度 $\mathcal{O}(k^2)$ ,其中 $k=d(N) \le 6720$ 。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define wr(a,b) cout << (a) << (b);
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)())
int n;
int gcd(int a,int b) { return b==0 ? a : gcd(b,a%b); }
void solve(int n,int d)
{
int a,b,u,v,l = floor(sqrt(n * 0.5));
if(n < 12 || n & 1) return;
for(a = ceil(sqrt(n * 0.25)); a <= l; a++)
if(n % (a * 2) == 0)
{
b = n / (a * 2) - a;
if(gcd(a,b) == 1 && (a ^ b) & 1)
{
tie(u,v) = minmax(a*a - b*b, 2*a*b);
wr(u * d, ' ');wr(v * d, ' ');wr((a * a + b * b) * d, '\n');
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cin >> n;
for(int k=1; k * k <= n; k++)
if(n % k == 0) { solve(n/k, k); k * k != n && (solve(k,n/k),0); }
return 0;
}
参考文献:
[1] https://yhx-12243.github.io/OI-transit/?redirect=584
[2] https://zh.wikipedia.org/wiki/%E5%8B%BE%E8%82%A1%E6%95%B0