BZOJ 1041: [HAOI2008]圆上的整点 1041: [HAOI2008]圆上的整点

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 4547  Solved: 2042

[Submit][Status][Discuss]

Description

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

Input

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

Output

整点个数

Sample Input

4

Sample Output

4

HINT

科普视频

题解

x*x+y*y=r*r

y=sqrt((r-x)*(r+x))

设i=gcd(r-x,r+x),设A=(r-x)/i,B=(r+x)/i,显然gcd(A,B)=1。

那么y*y=i*i*A*B,因为A!=B,所以A和B一定都是平方数,设a=sqrt(A),b=sqrt(B),那么a*a+b*b=2*r/i。

那么枚举i,再枚举a,计算出b,再判断gcd(A,B)是否为1。

求出第一象限的点数都,ans=ans*4+4,因为坐标轴上有4个点。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;
LL r,ans;
LL gcd(LL x,LL y){
	if(!y)return x;
	return gcd(y,x%y);
}
bool check(LL x,LL y){
	if(gcd(x*x,y*y)==1&&x!=y)return true;
	return false;
}
int main(){
	scanf("%lld",&r);
	double k;
	for(LL i=1;i<=sqrt(2*r);i++){
		if((2*r)%i==0){
			for(LL j=1;j<=sqrt(r/i);j++){
				k=sqrt(2*r/i-j*j);
				if(k==floor(k))if(check(j,floor(k)))ans++;
			}
			if(2*r/i!=i){
				for(LL j=1;j<=sqrt(i/2);j++){
					k=sqrt(i-j*j);
					if(k==floor(k))if(check(j,floor(k)))ans++;
				}
			}
		}
	}
	printf("%lld
",ans*4+4);
	return 0;
}