2017年8月12日提高组T3 YMW的三角形

53 篇文章 0 订阅

Description


YMW终于思考完数学题了,因为数学给人力量,所以他现在浑身都充满了力量。然而lyy俯视YMW,不屑地说道,你小学数学题都不会做,还在这嚣张?你看我们的电脑屏幕,可以是一个二维直角坐标系,你把手上那把三角板放在屏幕上,现在你告诉我它的每个顶点能否都在整数点上吗?(整数点:一个点,它的x和y坐标都为整数)

Input


多组数据,每组数据三个数表示三角形的三条边
输入以文件结束结尾

Output


对于每组数据,如果可以则输出Yes,不可以则输出No

Hint


数据范围:
数据组数不超过10组,不少于5组
对于30%的数据,三边长均小于1 000
对于70%的数据,三边长均小于100 000
对于100%的数据,三边长均小于10 000 000

Source


BY BPM

Solution


绿色就是力量!

又是一题被大小写耽误的。。

这里写图片描述

如图,已知任意一个在平面直角坐标系中的三角形都可以被矩形套住。那么我们可以固定一个点不动,通过枚举图中的边x的长得到h并判断是否是整数。

同理,我们可以通过海伦公式求面积,求a边上的高ha。那么通过ha/b可以确定夹角的大小,x/a同理。那么剩下的三角形就出来了,判断剩下的点是否是整点即可

但是,这样会面临卡精度的问题,例如92295 6688 92537这组数据,于是我可耻地看了一波标

这里写图片描述
我们可以通过平移旋转的方式改变三角形的位置,那么我们固定三角形在原点,可以发现旋转相当于以原点为圆心作半径为a的 1/4 圆,以原点为圆心作半径为b的1/2圆。

已知在半径为r的圆上点都满足 x2+y2=r2 ,通过枚举x坐标我们可以找出所有的整点,枚举判断是否存在两点距离为c即可。根据某项定理可得这样的整点不会超过 n 个,这样就是O(n)的了。

根据对称性我们只用找a/2次,b/2次,a、b为最短两边

Code


#include <stdio.h>
#include <math.h>
#include <vector>
#define rep(i, st, ed) for (ll i = st; i <= ed; i += 1)
#define EPS 1e-6
#define ll long long
#define db double
struct pos{ll x, y;}va[10001],vb[10001];
inline void swap(ll &a, ll &b){a^=b;b^=a;a^=b;}
inline bool teg(db x){return fabs(x - floor(x)) <= EPS;}
int main(void){
    int ra, rb, rc;
    while (~scanf("%d %d %d", &ra, &rb, &rc)){
        ll a = ra, b = rb, c = rc;
        if (b < a && b < c){swap(a, b);}
        if (c < a && c < b){swap(a, c);}
        if (c < b){swap(b, c);}
        int cntA = 0, cntB = 0;
        rep(x, 0, a / 2){
            db y = sqrt(a*a*1.0-x*x*1.0);
            if (fabs(y-(int)y)<=EPS){
                va[++ cntA] = (pos){x, y};
                va[++ cntA] = (pos){y, x};
            }
        }
        rep(x, 0, b / 2){
            db y = sqrt(b*b*1.0-x*x*1.0);
            if (fabs(y-(int)y)<=EPS){
                vb[++ cntB] = (pos){x, y};
                vb[++ cntB] = (pos){x, -y};
                vb[++ cntB] = (pos){y, x};
                vb[++ cntB] = (pos){y, -x};
            }
        }
        int ans = 0;
        rep(i, 1, cntA){
            rep(j, 1, cntB){
                pos ta = va[i], tb = vb[j];
                db d = sqrt((ta.x-tb.x)*(ta.x-tb.x)*1.0+(ta.y-tb.y)*(ta.y-tb.y)*1.0);
                if (fabs(c-d)<=EPS){
                    ans = 1;
                    break;
                }
            }
            if (ans){break;}
        }
        if (ans){puts("Yes");}
        if (!ans){puts("No");}
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值