【牛客练习赛51】C - 勾股定理【数学】

题目大意:

题目链接:https://ac.nowcoder.com/acm/contest/1083/C
给出直角三角形其中一条边的长度 n n n,你的任务是构造剩下的两条边,使这三条边能构成一个直角三角形。


思路:

分类讨论。

  • 如果 n ≤ 2 n\leq 2 n2,显然无解。
  • 如果 n n n是奇数,那么显然存在 a = ⌊ n 2 2 ⌋ , b = ⌊ n 2 2 ⌋ + 1 a=\lfloor\frac{n^2}{2}\rfloor,b=\lfloor\frac{n^2}{2}\rfloor+1 a=2n2,b=2n2+1,这样 b 2 − a 2 = ( b + a ) ( b − a ) = 2 ⌊ n 2 2 ⌋ + 1 = n 2 b^2-a^2=(b+a)(b-a)=2\lfloor\frac{n^2}{2}\rfloor+1=n^2 b2a2=(b+a)(ba)=22n2+1=n2。这样就构造出了一组勾股数。
  • 如果 n n n是偶数,那么就把 n n n写成 k × 2 p k\times 2^p k×2p,其中 k k k为奇数。
  • 如果 k > 1 k>1 k>1,那么就直接按照奇数的方法计算出另外两个数字,然后全部乘上 2 p 2^p 2p
  • 如果 k = 1 k=1 k=1,那么 n n n就是 2 p 2^p 2p。这样的话我们就另 t = n 4 t=\frac{n}{4} t=4n,显然 t t t不会是小数。那么利用勾股数 3 , 4 , 5 3,4,5 3,4,5,答案就是 3 t , 5 t 3t,5t 3t,5t

好像是有通项公式的,但是我太菜了不会


代码:

#include 
using namespace std;
typedef long long ll;

int a,b;
ll p;

int main()
{
	scanf("%d",&a);
	if (a==1 || a==2 || a==0)
		return !printf("-1");
	if (a&1)  //奇数
		return !printf("%lld %lld",(ll)a*(ll)a/2LL,(ll)a*(ll)a/2LL+1LL);
	for (p=1,b=a;!(b&1);b/=2,p*=2LL) ;  //计算k
	if (b!=1)  //可以转换成某个不为1的奇数
		printf("%lld %lld",(ll)b*(ll)b/2LL*p,((ll)b*(ll)b/2LL+1LL)*p);
	else  //为2^t
		printf("%lld %lld",3LL*(a/4),5LL*(a/4));
	return 0;
}

你可能感兴趣的:(数论,数学)