为了考虑方便,把问题视为以下模型:
对于任意的
1≤x<r
,求出满足
r2−x2
是完全平方数的
x
的个数,并把结果加
求
x
的个数仍然是暴力统计,但是此题可以利用
怎样求出这个必要条件呢?首先,把
r2−x2
化为
(r+x)(r−x)
。
思考
ab
为完全平方数的条件。可以看出,如果
ab
是完全平方数,那么
agcd(a,b)∗bgcd(a,b)
一定也是完全平方数,反过来也一样(因为
gcd(a,b)2
是完全平方数)。此时设
u=agcd(a,b),v=bgcd(a,b)
,那么
u
和
再看
gcd(r+x,r−x)
的取值。容易得出,
gcd(r+x,r−x)=gcd(r−x,2x)
。设
d=gcd(r−x,2x)
。
当
d|x
时,则有
gcd(r−x,2x)=gcd(r−x,x)=gcd(r,x)
,此时
d
可以取
否则有
gcd(r−x,2x)=2gcd(r−x,x)=2gcd(r,x)
,此时
d
可以取
从上面推出,
d=gcd(r+x,r−x)
的取值范围为
r
的每一个约数和每一个约数的两倍(注意去重)。
考虑枚举
1、必须要有
2、为避免重复,必须判断是否
gcd(r+x,r−x)=d
。
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e4 + 5;
int r, tot; ll Ans, a[N];
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
int main() {
int i, d, S, j, cc = 0; cin >> r; S = sqrt(r);
for (i = 1; i <= S; i++)
if (r % i == 0) {
a[++cc] = i; a[++cc] = 2ll * i;
if (r / i != i) a[++cc] = r / i,
a[++cc] = 2ll * (r / i);
}
sort(a + 1, a + cc + 1); tot = unique(a + 1, a + cc + 1) - a - 1;
for (j = 1; j <= tot; j++) {
d = a[j]; for (i = 1; 1ll * i * i * d <= r; i++) {
int x = r - i * i * d; if (x <= 0 || x >= r) continue;
if (gcd(1ll * r + x, 1ll * r - x) != d) continue;
ll w = 1ll * r * r - 1ll * x * x;
ll s = sqrt(w); if (s * s == w) Ans++;
}
}
cout << (Ans + 1) * 4 << endl;
return 0;
}