题目链接:bzoj 1041: [HAOI2008]圆上的整点
题意:给定一个圆 ( x 2 + y 2 = r 2 ) (x^2+y^2=r^2) (x2+y2=r2),在圆周上有多少个点的坐标是整数。
思路:先化简
x
2
=
r
2
−
y
2
=
(
r
−
y
)
∗
(
r
+
y
)
x^2 = r^2-y^2 = (r-y) * (r+y)
x2=r2−y2=(r−y)∗(r+y) 我们用
d
∗
A
=
(
r
−
y
)
d*A = (r-y)
d∗A=(r−y),
d
∗
B
=
(
r
+
y
)
d*B = (r+y)
d∗B=(r+y)其中
d
=
g
c
d
(
r
−
y
,
r
+
y
)
d = gcd(r-y, r+y)
d=gcd(r−y,r+y),限制
y
>
0
y > 0
y>0。
这样有
x
2
=
d
2
∗
A
∗
B
x^2 =d^2*A*B
x2=d2∗A∗B以及
d
∗
A
+
d
∗
B
=
2
∗
r
d*A + d*B = 2*r
d∗A+d∗B=2∗r。
r
r
r是已经知道的,我们就可以通过枚举因子d来构造
A
+
B
A+B
A+B的值
m
m
m。根据
x
2
=
d
2
∗
A
∗
B
x^2 = d^2*A*B
x2=d2∗A∗B且
A
,
B
互
质
A,B互质
A,B互质那么
A
,
B
A,B
A,B一定是完全平方数。这样得到
a
2
+
b
2
=
m
a^2+b^2 = m
a2+b2=m,再用一次枚举就可以了。
时间复杂度 O ( s q r t ( 2 ∗ r ) 2 ) O(sqrt(2*r)^2) O(sqrt(2∗r)2)
A C AC AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#define PI acos(-1.0)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define fi first
#define se second
#define ll o<<1
#define rr o<<1|1
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 2*1e6 + 1;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
void getmax(int &a, int b) {a = max(a, b); }
void getmin(int &a, int b) {a = min(a, b); }
void add(LL &x, LL y) { x += y; x %= MOD; }
LL gcd(LL a, LL b) {
return b == 0 ? a : gcd(b, a%b);
}
bool judge(LL a, LL b, LL d, LL r) {
LL y = r - d * a * a;
return y > 0 && d * b * b == r + y && gcd(a, b) == 1;
}
int main()
{
LL r; scanf("%lld", &r);
// LL s = 0;
// for(int x = -r; x <= r; x++) {
// for(int y = -r; y <= r; y++) {
// if(x * x + y * y == r * r)
// s++;
// }
// }
// printf("%lld\n", s);
if(r == 0) {
printf("1\n");
return 0;
}
LL ans = 0;
for(LL i = 1; i <= sqrt(2*r); i++)
{
if((2*r) % i == 0) {
LL m = 2 * r / i;
for(LL a = 1; a <= sqrt(m); a++) {
LL B = m - a * a; LL b = sqrt(B);
if(b * b == B) {
if(judge(a, b, i, r)) {
ans++;
//cout << a << " " << b << " " << i << endl;
}
}
}
m = i;
for(LL a = 1; a <= sqrt(m); a++) {
LL B = m - a * a; LL b = sqrt(B);
if(b * b == B) {
if(judge(a, b, 2 * r / i, r)) {
ans++;
//cout << a << " " << b << " " << 2 * r / i << endl;
}
}
}
}
}
printf("%lld\n", ans * 4 + 4);
return 0;
}
圆上整数点计数

本文介绍了一种高效算法,用于计算给定半径的圆周上整数坐标的点的数量。通过数学化简和枚举因子的方法,实现了一个时间复杂度为O(sqrt(2*r))^2的算法。
856

被折叠的 条评论
为什么被折叠?



