大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

洛谷P2508 [HAOI2008]圆上的整点

结论题 数学

做这道题之前首先要知道勾股方程的通解

勾股方程:\(x^2+y^2=r^2\)的通解为x = \(d*\frac{a^2-b^2}{2}\), y = \(d*a*b\), r = \(d*\frac{a^2+b^2}{2}\)

其中a, b为互质的正整数,d为任意实数

其实也就是勾股数乘上一定的倍数,简化:

x = \(\frac{a^2-b^2}{2}\), y = \(a*b\), r = \(\frac{a^2+b^2}{2}\)

然后我们考虑使得x, y为正整数的方程的解,此时d为正整数且为2r的约数,我们只需枚举2r的约数,然后枚举有多少个满足条件的\(a^2+b^2\)即可

因为x>0,故a>b,因此我们只需要枚举\(\sqrt{\frac{r}{d}}\)个b即可,若a,b互质且\(a^2+b^2=\frac{2*r}{d}\),令ans++。

最后原题要求x,y的整数解,(x,y)可以在4个象限中,再加上坐标轴上的四个点,最终答案为ans*4+4

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define int long long

int r,ans;

int gcd(int a,int b){ return b?gcd(b,a%b):a; }
void calc(int d){
	int x=2*r/d,i;
	for(i=1;i*i*2<x;++i){
		int t=x-i*i,j=sqrt(t);
		if(j*j==t&&gcd(i,j)==1) ++ans;
	}
}

void work(){
	for(int i=1;i*i<=2*r;++i){
		if(2*r%i) continue;
		calc(i);
		if(2*r/i!=i) calc(2*r/i);
	}
}

signed main(){
	cin>>r;
	work();
	cout<<ans*4+4;
	return 0;
}
posted @ 2019-10-10 11:31  White_star  阅读(155)  评论(0编辑  收藏  举报
}