bzoj 1041: [HAOI2008]圆上的整点

本文介绍了解决HAOI2008竞赛中圆上整点计数问题的方法。通过数学推导,利用圆的方程和约数特性,设计了一种高效算法,在大输入范围内快速找出圆周上所有整数坐标的点。

1041: [HAOI2008]圆上的整点

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 4140   Solved: 1875
[ Submit][ Status][ Discuss]

Description

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

Input

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

Output

  整点个数

Sample Input

4

Sample Output

4


因为n特别大,所以枚举肯定超时

那怎么办呢?

圆的方程式:X²+Y² = R²

那么可得Y² = R²-X² = (R+X)*(R-X)

令d = Gcd(R+X, R-X)

那么有Y² = d²*(R+X)/d*(R-X)/d

再设A = (R+X)/d,B = (R-X)/d

那么有Y² = d²*A*B,所以要想Y是整数,A*B一定要是一个完全平方数

又因为Gcd(A, B)==1,所以A和B一定都是完全平方数

到这就好办了

A = a², B = b²

那么有(R+X)/d, = (R-X)/d

a²+b² = 2*R/d

这说明d一定是2*R的一个约数,只要枚举2*R的约数d,

对于2*R%d==0,再枚举对应的a和b是多少,之后判断一波A和B是否互质即可,只要互质ans++

枚举约数都是更号的复杂度,所以不用担心超时

因为4个象限+4个坐标轴上的点

所以最后答案×4再+4


#include<stdio.h>
#include<math.h>
#define LL long long
LL Gcd(LL a, LL b)
{
	if(a%b==0)
		return b;
	return Gcd(b, a%b);
}
int main(void)
{
	LL R, d, i, j, ans;
	while(scanf("%lld", &R)!=EOF)
	{
		ans = 0;
		for(d=1;d*d<=2*R;d++)
		{
			if((2*R)%d==0)
			{
				for(i=1;i*i<=R/d;i++)
				{
					j = sqrt(2.0*R/d-i*i);
					if(i*i+j*j==2*R/d && Gcd(i*i, j*j)==1 && i!=j)
						ans++;
				}
				if(d*d==2*R)
					continue;
				for(i=1;i*i<=d/2;i++)
				{
					j = sqrt(1.0*d-i*i);
					if(i*i+j*j==d && Gcd(i*i, j*j)==1 && i!=j)
						ans++;
				}
			}
		}
		printf("%lld\n", ans*4+4);
	}
	return 0;
}




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值