湖南大学第十四届ACM程序设计大赛 K The Right-angled Triangles

链接:https://ac.nowcoder.com/acm/contest/338/K
来源:牛客网

题目描述

Consider the right-angled triangles with sides of integral length.

Give you the integral length of  the hypotenuse of a right-angled triangle.  Can it construct a right triangle with given hypotenuse c such that the two legs of the triangle are all . integral length?

输入描述:

There are several test cases. The first line contains an integer T(1≤T≤1,000), T is the number of test cases.

The following T lines contain T test cases, each line contains one test case. For each test case, there is an integer : c, the length of hypotenuse.(1≤c≤45,000).

输出描述:

For each case, output Yes if it can construct a right triangle with given hypotenuse c and sides of integral length , No otherwise.

示例1

输入

复制

4
5
6
15
13

输出

复制

Yes
No
Yes
Yes

题目大意:

考虑具有整型长度的直角三角形。
给出直角三角形斜边的长度。它能不能构造一个直角三角形,斜边c是已知的,使得三角形的两条边都是整数?

输入描述:
有几个测试用例。第一行包含一个整数T(1≤T≤1000),T是测试用例的数量。
下面的T行包含T个测试用例,每一行包含一个测试用例。对于每个测试用例,都有一个整数:c,斜边的长度。(c 1≤≤45000)。
输出描述:
对于每一种情况,如果它能构造出斜边c和整型长度的直角三角形,则输出Yes,否则输出No。
示例1
输入
4
5
6
15
13
输出
Yes
No
Yes
Yes

分析:

有两种方法:

1。暴力枚举:题目提供的可能测试数据相对较弱,所以可以利用枚举的方法枚举每一个整数进行尝试,但枚举范围要缩小到

i*i<=c/2;c/2以后的数跟之前就重复了,同时如果不缩小范围的话就超时了。

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
    long long c,n,ans,a,b;
    cin>>n;//输入测试次数
    while(n--)
    {
        ans=0;
        cin>>c;//输入斜边
        c=c*c;
        for(int i=1;i*i<=c/2;i++)//只需要尝试c/2之前的即可,c/2之后的重复
        {
            a=sqrt(c-i*i);//求另一个直角边,如果符合条件答案为1直接跳出循环
            if(a*a==c-i*i)
            {
				ans=1;
            	break;
        	}
        }
        if(ans==1)
        cout<<"Yes"<<endl;
        else
        cout<<"No"<<endl;
    }
}

2.这个题很容易想到的一个思路就是暴力枚举。是的,我们给的解题方法也是暴力枚举。但是,直接枚举的复杂度是O(c2),会超时(TLE)。所以我们需要将问题转化一下,使得枚举的复杂度是O(c)。

• 如果三角形三边满足如下关系,则是直角三角形。
• a=m^2-n^2

• b=2mn
• c=m^2+n^2

解释:这是本原勾股数  因为
a^2+b^2
=(m^4 + n^4)- 2×m^2×n^2+(2mn)^2
=(m^2+n^2)^2=c^2 
• 所以如果斜边长度能够表示成2个正整数的平方和,则能使得三边都是正整数。这样枚举的复杂度是O( c)。
• 另外,如果斜边长度是一个合数,其有一个因子能表示为2个正整数的平方和,那么也能使得三边都是正整数。比如c=15,有因
子5=12+22,那么也是可以构成三边全是整数的直角三角形,每边长度乘以3即可。就是( 9, 12, 15)

#include <stdio.h>
#define N 45001
int MK[N]={0},SQ[213];
int i,j,k;
//MK数组标记能否是整数三角形,为0表示不能,非0表示可以, SQ数组记录数的平方值
int main()
{
	for(i=1;i<213;++i)
		SQ[i]=i*i;
	for(i=1;i<213;++i)
		for(j=i+1;j<213&&(k=SQ[i]+SQ[j])<N;++j)
			MK[k]=1; //所有能写成2整数平方和的被标记为能
	for(i=5;i<22501;++i)
		if(MK[i]==1)
		for(j=2;(k=j*i)<N;++j)
			MK[k]=1; //所有含2整数平方和的因子的正整数被标记为能,类似于筛法求素数的思想
		scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&c);
		printf("%s\n",MK[c]?"Yes":"No");
	}
		return 0;
}

猜你喜欢

转载自blog.csdn.net/basketball616/article/details/86294590
今日推荐