1. 程式人生 > >湖南大學第十四屆ACM程式設計大賽 K The Right-angled Triangles

湖南大學第十四屆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;
}