勾股数 BZOJ 1041

        给定一个数z,求满足x^2+y^2=z^2的有序数对(x,y)有多少对。

        其实应该早在两年前就知道解法的,只不过当时太弱啥都没听懂%>_<%

        首先移项 x^2 = z^2-y^2

                       x^2 = (z-y)(z+y)

        令           d = gcd(z-y,z+y)

        则           x^2 = d*d*((z-y)/d)*((z+y)/d)

        计           A = (z-y)/d, B = (z+y)/d, 显然gcd(A,B) = 0

又因为            x^2为完全平方数,d^2为完全平方数,则A,B均为完全平方数

因此设            A = a*a, B = b*b,   

       则            a*a+b*b = 2*z/d

        所以,我们可以在O(sqrt(r))枚举出所有的d,对于每个d,我们可以用O(sqrt(d))枚举出所有的a,来判断b是否可行。

        看来勾股定理的题目都可以这样做耶,2年前的那道GDKOI统计x^2+y^2=z^2+1的还有待思考。

#include <cstdio>
#include <cmath>

using namespace std;

int ans,r;

long long gcd(long long a,long long b)
{
	return !b ? a : gcd(b,a%b);
}

void check(long long x)
{
	for (int a=1;a<=floor(sqrt(x/2));a++)
	{
		long long b2 = x-a*a;
		int b = floor(sqrt(b2));
		if (b*b == b2 && gcd(a*a,b2) == 1 && a != b) ans++;
	}
}

void solve(long long r)
{
	for (int d=1;d<=floor(sqrt(2*r));d++) if ((2*r)%d ==0)
	{
		check(2*r/d);
		check(d);
	}
} 

int main()
{
	scanf("%lld",&r);
	solve(r);
	printf("%lld\n",(ans+1)*4);
	return 0;
} 

update:当年KOI的x^2+y^2=z^2+1的数据范围是1e6,小很多,直接线性筛表勉勉强强卡过

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值