BZOJ系列1041《[HAOI2008]圆上的整点》题解

Description

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

Input

r

Output

整点个数

Sample Input

4

Sample Output

4

HINT

n<=2000 000 000


不得不吐槽一下,作为一名河南人,0708年那会我们河南水平很低,花钱让雅礼的朱全民老师出我们的省选题,

质量很高,但都不会做,这道题当时河南没一个人做出来,那时往往是可以60分就进队的,呵呵。

如今,我们河南的实力不说和浙江和牛棚湖南比,但是还是有很大提升的,这几年的省选题却开始糊弄了,

找郑州大学的人出不要钱的题,真是醉了,14年省选题考纯暴力,没动规没图论,数据还有错,

真是白瞎了这几年实力的增长,有实力了考简单题,没实力了要考各种难。

好吧!吐槽归吐槽,还是要好好面对的,希望明年省选靠点谱吧!

说题,很难,真的没有任何头绪,枚举肯定是不行的,所以就应该找找数学方法了。

以下转自某神犇blog:
//==========================分割线==========================
这里先只考虑x,y都大于0的情况


如果x^2+y^2=r^2,则(r-x)(r+x)=y*y


令d=gcd(r-x,r+x),r-x=d*u^2,r+x=d*v^2,显然有gcd(u,v)=1且u

有2r=d*(u^2+v^2),y=d*u*v,x=d(v^2-u^2)/2


枚举2r的约数d,再花费sqrt(2r/d)的时间枚举u,求出v=sqrt(2r/d-u^2)然后判断gcd(u,v)=1。

一个数字的平均约数个数为logn个,然后后面那个sqrt(2*r/d)在很多情况下都很小,所以比较快。


最后结果乘以4(四个象限)+4(坐标轴上)即可
//==========================分割线==========================

方法不得不称之曰奇妙,时间复杂度是一定不会超的,完美解决!

代码如下:

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
ll R,ans=0;
ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); }
void lyd(ll d)
{
	ll v;
	for(ll u=1;u<=(ll)sqrt(1.0*2*R/d);u++)
	{
		v=(ll)sqrt(1.0*2*R/d-u*u*1.0);
		if(gcd(v,u)==1&&u<=v&&d*(u*u+v*v)==2*R) ans++;
	}
}
int main()
{
	scanf("%lld",&R);
	for(ll i=1;i<=(ll)sqrt(1.0*R*2);i++)
		if(2*R%i==0)
		{
			if((ll)i*i!=2*R)
			{
				lyd(2*R/i);
				lyd(i);
			}
			else lyd(i);
		}
	printf("%lld\n",ans*4);
	return 0;
}


你可能感兴趣的:(BZOJ)