1079 三角形

Description
著名的数学家毕达哥拉斯可能从来都不曾想过有人居然会问他这样的一个问题:给出一个整数,存在多少个直角三角形,
它的某一条边的长度等于这个整数,而且其他边的长度也是整数。既然毕达哥拉斯不可能预见到有计算机的出现,
如果他回答不出来,那谁又能责怪他呢?但是现在既然你有了计算机,那么回答不出来就说不过去了。

输入格式 第一行有一个整数n,代表有多少个数据(1<=n<=20)。接下来有n行,每行代表一个数据。一个数据就是一个整数ai(a<=i<=n,1<=ai<=100)。

输出格式
每个数据都必须有相应的输出。两个数据的输出之间有一个空行。
对于每一个数据,如果找不到解,则输出一个空行。如果找到解,就把符合条件的所有直角三角形输出。每个三角形占一行,输出该三角形的另外两条边,
必须先输出长边,然后一个逗号,再输出短边。两个三角形之间不能有空行,而且必须按照长边降序排列。

输入样例
2
20
12

输出样例
101,99
52,48
29,21
25,15
16,12

37,35
20,16
15,9
13,5

/*
思路:
本题要求输入一个三角形的一条边长x,可能为直角边,可能为斜边;要求输出能够构成三条整数边长的三角形的所有情况.
流程分析:
①、当输入x为直角边时,则另外一条直角边i从1开始,计算由直角边i和直角边x构成的斜边temp=sqrt(i×i+x×x)是否是整数,如果是整数,则满足条件,按照要求输出 一直枚举到斜边与直角边i的差值小于1为止,i不再继续枚举
②、当输入x为斜边时,则一条直角边i从x-1开始,计算由斜边x和直角边i构成的另外一条直角边temp=sqrt(x×x-i×i)是否是整数,如果是整数,则满足条件,按照要求输出,一直到枚举到i<1
细节部分:
需要注意当x是直角边时,不知道最大满足条件另外一条直角边i的情况是如何,所以只能从直角边i=1开始枚举,但是输出的时候需要从大到小输出,所以用栈把满足条件的情况存储起来,后面统一出栈输出
而当x是斜边时,因为直角边i是从x-1开始往更小整数枚举,会出现重复情况,比如x为20 i为16 temp为12 和x为20 i为12 temp为16都满足情况,这时候可以利用用一个标记数组v[100000]去重
*/

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;
int main()
{
    int n,i, x;
    cin>>n;
    while (n--)
    {
        cin>>x;
        //直角边的情况
        i = 1;
        double c;
        int temp;
        int top = 0, s[100000][2] = {0}, v[100000] = {0};
        while (1)
        {
            c = x * x + i*i;//斜边的平方
            temp = (int)sqrt(c);//整型
            if (temp * temp == c)//如果由直角边x和另一条直角边i构成的斜边temp是整数,则将符合条件的两条边入栈
            {
                s[top][0] = temp, s[top][1] = i;
                top++;
            }
            if (sqrt(c) - i < 1)//如果斜边跟直角边i的差值小于1,则结束枚举
                break;
            i++;//枚举更大整数直角边i
        }
        //按照题目要求输出满足条件的情况
        while (top)
        {
            printf("%d,%d\n", s[top-1][0], s[top-1][1]);
            top--;
        }

        //斜边的情况
        i = x-1;
        while (1)
        {
            if (i < 1)//如果直角边i小于1,则结束枚举
                break;
            c = x * x - i * i;//另一条直角边的平方
            temp = sqrt(c);//另一条直角边temp
            if (temp * temp == c)//如果由斜边x和直角边i构成的另一条直角边temp是整数
            {
                if (v[i] == 1)//如果这个直角边i已经作为temp被输出过,则继续枚举
                {i--;continue;}
                if (temp < i)//按照格式输出
                    printf("%d,%d\n",i, temp);
                else if (temp >= i)
                    printf("%d,%d\n", temp,i);
                v[temp] = 1;//标记直角边temp和斜边x构成的另外一条直角边i出现过
            }
            i--;//继续枚举更小整数直角边i
        }
        printf("\n");//输出空行
    }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值