[HAOI2008]圆上的整点

Description
求一个给定的圆(x2+y2=r^2),在圆周上有多少个点的坐标是整数。

Input
只有一个正整数n,n<=2000 000 000

Output
整点个数

Sample Input
4

Sample Output
4


这种题肯定是要推柿子的啦~~~

\(X^2+Y^2=R^2\)

\(Y^2=(R-X)(R+X)\)

\(d=gcd(R-X,R+X),A=\dfrac{R-X}{d},B=\dfrac{R+X}{d}\)

所以\(y^2=d^2\times A\times B\)

因为\(y^2,d^2\)为完全平方数,因此\(A\times B\)也为完全平方数

由于\(gcd(A,B)=1\),因此\(A,B\)本身也是完全平方数

\(a^2=A,b^2=B\),由于\(gcd(A,B)=1\),因此\(A\ne B\),因此\(a\ne b\)

我们令\(a<b\),则可以得到\(a^2=\dfrac{R-X}{d},b^2=\dfrac{R+X}{d}\)

相加可得\(a^2+b^2=\dfrac{2R}{d}\),因此\(d\)\(2R\)的约数

于是我们可以在\(\sqrt{2R}\)的时间内枚举其约数,由于\(2a^2<\dfrac{2R}{d}\),因此我们可以直接枚举\(a\in[1,\sqrt{\dfrac{R}{d}}]\),然后计算出\(b\),再将其反代回求出\(A,B\),判断\(A,B\)是否满足条件

但是这样子我们只算出了处于第一象限的答案,根据圆的对称性,我们需要将答案乘上4,并且加上坐标轴上的4个点

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
	int x=0,f=1; char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline int read(){
	int x=0,f=1; char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)	putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
ll R,Ans;
ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
bool check(int a,int b){
	ll A=1ll*a*a,B=1ll*b*b;
	return (gcd(A,B)==1)&&(A!=B);
}
void work(ll x){
	for (int a=1;a*a<=x>>1;a++){
		int b=trunc(sqrt(x-a*a));
		if (1ll*a*a+1ll*b*b!=x)	continue;
		if (check(a,b))	Ans++;
	}
}
int main(){
	R=2ll*read();
	for (int i=1;1ll*i*i<=R;i++){
		if (R%i)	continue;
		work(i);
		if (R/i!=i)	work(R/i);
	}
	printf("%lld\n",4*Ans+4);
}
posted @ 2018-11-22 19:03  Wolfycz  阅读(498)  评论(0编辑  收藏  举报