给定一个数z,求满足x^2+y^2=z^2的有序数对(x,y)有多少对。
其实应该早在两年前就知道解法的,只不过当时太弱啥都没听懂%>_<%
首先移项 x^2 = z^2-y^2
x^2 = (z-y)(z+y)
令 d = gcd(z-y,z+y)
则 x^2 = d*d*((z-y)/d)*((z+y)/d)
计 A = (z-y)/d, B = (z+y)/d, 显然gcd(A,B) = 0
又因为 x^2为完全平方数,d^2为完全平方数,则A,B均为完全平方数
因此设 A = a*a, B = b*b,
则 a*a+b*b = 2*z/d
所以,我们可以在O(sqrt(r))枚举出所有的d,对于每个d,我们可以用O(sqrt(d))枚举出所有的a,来判断b是否可行。
看来勾股定理的题目都可以这样做耶,2年前的那道GDKOI统计x^2+y^2=z^2+1的还有待思考。
#include <cstdio>
#include <cmath>
using namespace std;
int ans,r;
long long gcd(long long a,long long b)
{
return !b ? a : gcd(b,a%b);
}
void check(long long x)
{
for (int a=1;a<=floor(sqrt(x/2));a++)
{
long long b2 = x-a*a;
int b = floor(sqrt(b2));
if (b*b == b2 && gcd(a*a,b2) == 1 && a != b) ans++;
}
}
void solve(long long r)
{
for (int d=1;d<=floor(sqrt(2*r));d++) if ((2*r)%d ==0)
{
check(2*r/d);
check(d);
}
}
int main()
{
scanf("%lld",&r);
solve(r);
printf("%lld\n",(ans+1)*4);
return 0;
}
update:当年KOI的x^2+y^2=z^2+1的数据范围是1e6,小很多,直接线性筛表勉勉强强卡过