头像

SXL

Untitled


访客:9206

离线:8小时前



SXL
1天前

AC的题解:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<stdio.h>
using namespace std;
#define eps 1e-8

int dcmp(double x){
    if(fabs(x)<eps)return 0;
    else return x<0 ? -1:1;
}

struct Point3{
    double x,y,z;
    Point3(double x=0,double y=0,double z=0):x(x),y(y),z(z){} 
};
bool operator==(const Point3& a,const Point3& b){
    return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0 && dcmp(a.z-b.z)==0 ;
}
typedef Point3 Vector3;
Vector3 operator+(Vector3 A,Vector3 B){
    return Vector3(A.x+B.x,A.y+B.y,A.z+B.z);
}
Vector3 operator-(Vector3 A,Vector3 B){
    return Vector3(A.x-B.x,A.y-B.y,A.z-B.z);
}
Vector3 operator*(Vector3 A,double p){
    return Vector3(A.x*p,A.y*p,A.z*p);
}
Vector3 operator/(Vector3 A,double p){
    return Vector3(A.x/p,A.y/p,A.z/p);
}

double Dot(Vector3 A,Vector3 B){return A.x*B.x+A.y*B.y+A.z*B.z;}
double Length(Vector3 A){return sqrt(Dot(A,A));}
double Angle(Vector3 A,Vector3 B){return acos(Dot(A,B)/Length(A)/Length(B));}


//叉积
Vector3 Cross(Vector3 A,Vector3 B){
    return Vector3(A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x);
}
double Area2(Point3 A,Point3 B,Point3 C){return Length(Cross(B-A,C-A));}
//点p在三角形p0p1p2中(利用面积法算点是否在三角形内,假定所有的点共面)
bool PointInTri(Point3 p,Point3 p0,Point3 p1,Point3 p2){
    double area1=Area2(p,p0,p1);
    double area2=Area2(p,p1,p2);
    double area3=Area2(p,p2,p0);
    return dcmp(area1+area2+area3-Area2(p0,p1,p2))==0;
}
//三角形p0p1p2是否和线段AB相交(此函数会把线段在平面上的情况视为不相交)
bool TriSegIntersection(Point3 p0,Point3 p1,Point3 p2,Point3 A,Point3 B,Point3& p){
    Vector3 n=Cross(p1-p0,p2-p0);
    if(dcmp(Dot(n,B-A))==0)return false;//平行或共面
    else{                               //直线AB和平面P0P1P2有唯一交点
        double t=Dot(n,p0-A)/Dot(n,B-A);
        if(dcmp(t)<0 || dcmp(t-1)>0)return false;//交点不在线段AB上
        p=A+(B-A)*t;                             //计算交点
        return PointInTri(p,p0,p1,p2);           //判断交点是否在三角形内
    }
}
//判断两个三角形是否有公共点
bool TriTriIntersection(Point3* T1,Point3* T2){
    Point3 p;
    for(int i=0;i<3;i++){
        if(TriSegIntersection(T1[0],T1[1],T1[2],T2[i],T2[(i+1)%3],p))return true;
        if(TriSegIntersection(T2[0],T2[1],T2[2],T1[i],T1[(i+1)%3],p))return true;
    }
    return false;
}
//*******************************************************************************
int main(){
    int T;cin>>T;
    while(T--){
        Point3 T1[3],T2[3];
        for(int i=0;i<3;i++)cin>>T1[i].x>>T1[i].y>>T1[i].z;
        for(int i=0;i<3;i++)cin>>T2[i].x>>T2[i].y>>T2[i].z;
        cout<<(TriTriIntersection(T1,T2) ? "1\n":"0\n");
    }return 0;
}

我在UVA上RE的:

/*
UVA11275 3D Triangles
题意:问两个三角形是否有公共点 
思路:把一个三角形拆分成三条线段就好 
*/
#include <bits/stdc++.h>
using namespace std;
const double eps=1e-8;
struct Point3
{
    double x,y,z;
    Point3 (double x=0,double y=0,double z=0) : x(x),y(y),z(z) {}
    Point3 read_Point3() { scanf( "%lf%lf%lf",&x,&y,&z ); }
};
typedef Point3 Vector3;

Vector3 operator + (Vector3 A,Vector3 B) 
{ return Vector3(A.x+B.x,A.y+B.y,A.z+B.z); }
Vector3 operator - (Point3 A,Point3 B) 
{ return Vector3(A.x-B.x,A.y-B.y,A.z-B.z); }
Vector3 operator * (Vector3 A,double p) 
{ return Vector3(A.x*p,A.y*p,A.z*p); }
Vector3 operator / (Vector3 A,double p) 
{ return Vector3(A.x/p,A.y/p,A.z/p); }
int dcmp( double x) 
{ if ( fabs(x)<eps ) return 0; else return x<0 ? -1 : 1; }
bool operator==( const Point3& a,const Point3& b )
{ return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0 && dcmp(a.z-b.z)==0; }
double Dot(Vector3 A,Vector3 B) 
{ return A.x*B.x+A.y*B.y+A.z*B.z; }     //三维点积 
double Length( Vector3 A ) 
{ return sqrt( Dot(A,A) ); }
double Angle( Vector3 A,Vector3 B ) 
{ return acos( Dot(A,B)/Length(A)/Length(B) ); }
//点p到平面p0-n的距离(n为平面法向量,垂直于平面) 
double DistanceToPlane (Point3 p,Point3 p0,Vector3 n) 
{ return fabs(Dot(p-p0,n))/Length(n); }
//p在平面p0-n的投影 
Point3 GetPlaneProjection (Point3 p,Point3 p0,Vector3 n) 
{ double d=Dot( p-p0,n )/Length(n); return p+n*d; }
//直线p1-p2到平面p0-n的交点(假定唯一) 
Point3 LinePlaneIntersection (Point3 p1,Point3 p2,Point3 p0,Vector3 n)
{ Vector3 v=p2-p1; double t=( Dot(n,p0-p1)/Dot(n,p2-p1) ); return p1+v*t; }
//三维叉积
Vector3 Cross (Vector3 A,Vector3 B)
{ return Vector3( A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x ); } 
double Area2( Point3 A,Point3 B,Point3 C )
{ return Length( Cross(B-A,C-A) ); }
//点p在△p0p1p2
bool PointInTri ( Point3 P,Point3 p0,Point3 p1,Point3 p2 )
{ 
    double area1=Area2(P,p0,p1),area2=Area2(P,p1,p2),area3=Area2(P,p2,p0);
    return dcmp(area1+area2+area3-Area2(p0,p1,p2))==0; 
} 
//△p0p1p2是否和线段AB相交
bool TriSegIntersection( Point3 p0,Point3 p1,Point3 p2,Point3 A,Point3 B,Point3 &p )
{
    Vector3 n=Cross( p1-p0,p2-p0 );
    if ( dcmp(Dot(n,B-A))==0 ) return 0;        //平行或者共面
    else
    {
        double t=Dot(n,p0-A)/Dot(n,B-A);
        if ( dcmp(t)<0 || dcmp(t-1)>0 ) return 0;       //交点不在线段上
        p=A+(B-A)*t; return PointInTri(p,p0,p1,p2);     //判断交点是否在三角形内 
    } 
} 

bool TriTriIntersection( Point3 *T1,Point3 *T2 )
{
    Point3 p;
    for ( int i=0; i<3; i++ )
    {
        if ( TriSegIntersection( T1[0],T1[1],T1[2],T2[i],T2[(i+1)%3],p ) ) return 1;
        if ( TriSegIntersection( T2[0],T2[1],T2[2],T1[i],T1[(i+1)%3],p ) ) return 1;
    }
    return 0;
}

int main()
{
    int T; scanf( "%d",&T );
    while ( T-- )
    {
        Point3 T1[3],T2[3];
        for ( int i=0; i<3; i++ ) T1[i].read_Point3();
        for ( int i=0; i<3; i++ ) T2[i].read_Point3();
        printf( "%d\n",TriTriIntersection( T1,T2 ) ? 1 : 0 );
    }
}

UVA11275,求大佬帮忙看看哪里不一样!谢!!!!(调到自闭)



活动打卡代码 AcWing 1828. 魔法值

SXL
2天前
/*
ai的范围是2^32,直接做肯定炸掉。考虑是2的幂次,可以用倍增解决。
首先,用dis[i,j,k]表示i到j长度为2^k的路径数量。用Floyd计算dis数组。 
对于一个询问,把ai二进制拆分。f[i,j]表示前j个二进制里的1,从1到i的方案数。 
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=110,M=35;
ll f[N][M],road[N][N][M],a[N],a1[M];
int n,m,q;

int main()
{
    scanf( "%d%d%d",&n,&m,&q ); 
    for ( int i=1; i<=n; i++ )
        scanf( "%lld",&a[i] );
    for ( int i=1,ta,b; i<=m; i++ )
        scanf( "%d%d",&ta,&b ),road[ta][b][0]=road[b][ta][0]=1;

    for ( int i=1; i<M; i++ )
     for ( int l=1; l<=n; l++ )
      for ( int j=1; j<=n; j++ )
       for ( int k=1; k<=n; k++ )
        road[j][k][i]+=road[j][l][i-1]*road[l][k][i-1];
    for ( int i=1; i<=q; i++ )
    {
        ll tot=0; ll tmp,ans=0; memset( f,0,sizeof(f) );
        scanf( "%lld",&tmp ); 
        for ( int j=M-1; j>=0; j-- )
            if ( (1ll<<j)<=tmp ) a1[++tot]=j,tmp-=1ll<<j;
        f[1][0]=1;
        for ( int j=1; j<=tot; j++ )
         for ( int k=1; k<=n; k++ )
          for ( int l=1; l<=n; l++ )
            f[k][j]+=f[l][j-1]*road[l][k][a1[j]];
        for ( int j=1; j<=n; j++ )
            f[j][tot]&=1;
        for ( int j=1; j<=n; j++ )
            if ( f[j][tot] ) ans^=a[j];

        printf( "%lld\n",ans );
    }
}


活动打卡代码 AcWing 1827. 水壶

SXL
3天前
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,k,a[N],ans=0;

int main()
{
    scanf( "%d%d",&n,&k ); a[0]=0;
    for ( int i=1; i<=n; i++ )
        scanf( "%d",&a[i] ),a[i]+=a[i-1];

    for ( int i=k+1; i<=n; i++ )
        ans=max( ans,a[i]-a[i-k-1] );

    printf( "%d",ans );
}



SXL
4天前

水一波更新。 我的古老分享
来自一名终于看懂线性基的蒟蒻。 感谢这篇博文
这里写的会比较简略,更加详尽的看如上链接。

线性基是啥

线性基是一种特殊的基,它通常会在异或运算中出现,它的意义是:假设若干数的线性基是一组数a1,a2,…an,其中ax的最高位的1在第x位。并且通过原集合S的某一个最小子集S1使得S1内元素相互异或得到的值域与原集合S相互异或得到的值域相同。
具体可以通过性质理解一下。

线性基的性质

  1. 线性基能相互异或得到原集合的所有相互异或得到的值。
  2. 线性基是满足性质1的最小的集合
  3. 线性基没有异或和为0的子集

线性基的插入与删除

我们考虑插入的操作,令插入的数为 x ,考虑 x 的二进制最高位 i ,
• 若线性基的第 i 位为 0 ,则直接在该位插入 x ,退出;
• 若线性基的第 i 位已经有值 ai ,则 x =x⊕ai ,重复以上操作直到 x=0。
如果退出时 x=0 ,则此时线性基已经可以表示原先的 x 了;反之,则说明为了表示 x ,往线性基中加入了一个新元素。

void insert( ll x )
{
    for ( int i=N; ~i; i-- )
        if ( x&(1ll<<i) )
        {
            if ( a[i] ) x^=a[i];
            else
            {
                a[i]=x; return;
            }
        }
}

代码如上,读入一个插入一个即可。a表示的是线性基数组。

查询异或最值

查询最小值:考虑插入的过程,因为每一次跳转操作,x的二进制最高位必定单调降低,所以不可能插入两个二进制最高位相同的数。
而此时,线性基中最小值异或上其他数,必定会增大。所以,直接输出线性基中的最小值即可。
需要注意的是,线性基是不能异或出0的,也就是需要特判能不能搞出0来

bool flag;//可以表示0
ll qmin(ll res=0)
{
    if(flag) return 0;
    for(reg int i=0; i<=MN; i++)
        if(a[i]) return a[i];
}//自己没写,网上找来的代码,应该没问题叭。。。

异或最大值:从高到低遍历线性基,考虑到第 i 位时,如果当前的答案 x 第 i 位为 0 ,就将 x 异或上 ai ;否则不做任何操作。显然,每次操作后答案不会变劣,最终的 x 即为答案。
同样,我们考虑对于一个数 x ,它与原数列中的数异或的最值如何获得。用与序列异或最大值类似的贪心即可解决。(就是把ans初始值改成x)
模板题

ll ans=0;
for ( int i=N; ~i; i-- )
    ans=max( ans,ans^a[i] );
好像有另外一种for里面的写法(也就是如上题解里的写法):
if ( !(ans&(1ll<<i)) ) ans=ans^a[i];
(实测都能过)(注:~i 相当于 i>=0)

求第k小

首先,线性基的构造方式跟之前不太一样了,我们知道,线性基是以每个二进制为最高位存一个数的,容易想到把 k 进制分解,这样的话,只需要改点限制:规定 pi 的值的最高位是第 i 位,且在此基础上 pi 最小。
考虑之前的 pi,它除了在第 i 位有个 1 外,在更低的位还有若干个 1。那是否可以用线性基中的某些数,尽量消去低位的那些 1? 这个很好做,往线性基插入一个新数时,用这个 pi 更新 p 数组的其它所有值就行了。
详细做法:
  对于低位
   现在插入的一个数放到了 pi,它在一个更低的二进制位(设其为第 j 位)上为 1,且 pj 已被赋过值,那就把 pi 更新为 pi⨁pj。为了方便,从大到小枚举 j 即可。
  对于高位
   只考虑低位显然不对,因为有可能 pi 的第 j 个二进制位为 1,而 pj 此时可能没有值,但它以后被赋了值,这种情况下也应该用 pj 更新 pi。我们只能用赋值晚的更新赋值早的,所以对于插入的一个数 pi,不仅要用更低位的 pj 更新它,还要用它更新更高位的 pj。依然从大到小枚举 j。

其实这才是线性基的通用构造方式(比如对于模板题,多出来的要求对答案没有影响,因此该构造方案可以兼容使用)。另外说一下,换个角度看这个构造方式,其实就是标准的高斯消元+矩阵消成三角形,所谓的把不在对角线上的 1 能消掉就消掉,其实也就是让每行的数最小。
如上改变线性基的构造方式后,把 k−1 二进制分解,若第 i 位为 1 就把 ans 异或上 pi即可

如果要求至少选一个数,但你可以选出若干个数(至少一个)的异或和为 0(这种情况下 0 才是最小的异或和),然而线性基中的数并不能异或出 0(因为任意两个数的最高位都不相同,至少最大的那个数的高位就消不掉),所以要特判能否异或出 0。回顾一下线性基的构造:你在往线性基中插数的时候,如果最终这个数没被插入,那它一定就被异或成 0 了。这说明原集合 S 的若干个数(至少一个)能异或出 0,这时把 k 改为 k−1 即可
模板题——HDU3949

//HDU3949
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
const int N=63;
int n,cnt,tot;
ll a[65],b[65];
bool flag=0;

void insert( ll x )
{
    for ( int i=N; ~i; i-- )
        if ( x&(1ll<<i) )
        {
            if ( a[i] ) x^=a[i];
            else
            {
                a[i]=x; 
                for ( int j=i-1; ~j; j-- )          
                    if ( a[j] && a[i]&(1ll<<j) ) a[i]^=a[j];
                for ( int j=N; j>i; j-- )       //¸üÐÂд·¨ÓÐËùÇø±ð 
                    if ( (a[j]>>i)&1 ) a[j]^=a[i];
                return;
            }
        }
    if ( x==0 ) flag=1;
}

ll solve( ll k )
{
    ll ans=0; k-=flag;      //ÌØÅÐ0 
    if ( k>=(1ll<<cnt) ) return -1;
    for ( int i=0; i<=N; i++ )
        if ( (k>>i)&1 ) ans^=b[i];
    return ans;
} 

int main()
{
    int T; scanf( "%d",&T );
    for ( int t=1; t<=T; t++ )
    {
        memset( a,0,sizeof(a) ); flag=0;
        memset( b,0,sizeof(b) );
        scanf( "%d",&n ); 
        for ( int i=1; i<=n; i++ )
        {
            ll x; scanf( "%lld",&x ); insert( x );
        }   

        cnt=0; tot=0; 
        for ( int i=0; i<=N; i++ )      //×¢ÒâÒªÕûºÏaÊý×é
            if ( a[i] ) cnt++,b[tot++]=a[i];
        int Q; scanf( "%d",&Q ); printf( "Case #%d:\n",t );
        while ( Q-- )
        {
            ll k,ans=0; scanf( "%lld",&k );
            printf( "%lld\n",solve(k) ); 
        }
    }
}



SXL
7天前

RT,UVA12413不会QAQ



问题 关于CF

SXL
21天前

求问各位大佬,大概什么阶段打div几比较合适?




SXL
22天前

其实那天本来想在cf里发的,结果发现要英文,英语不好,就咕了……
今天整u盘找出来了QAQ

FHQ-Treap,就是不用旋转的函数式平衡树。(FHQ是范浩强orz)
基本思想:通过对平衡树进行分割(split)和合并(merge)完成维护平衡。
基本操作:插入,删除,查询排名,查询数值,求前驱,求后继

首先Treap,真身为二叉搜索树(BST),即左儿子<父节点<右儿子。为了避免数据毒瘤造成树很长,
导致效率下降,平衡树诞生了。
Splay优良解释
Treap就是给每个结点赋一个random值,在BST的前提下维护random的值的堆性质。
在Splay中最难理解的就是rotate,但是FHQ更加板子,也更好理解,个人比较喜欢。

FHQ-Treap 学习笔记
学军day2 2020.1.19

#include <bits/stdc++.h>
using namespace std;
struct node
{
    int val,rnd,l,r,size;
}tr[1000010];

int merge( int x,int y )        //合并两个Treap(保证x的值小于y) 
{
    if ( !x && !y ) return x+y;
    update( x ); update( y );          //就是根据左右子节点的size更新父节点,这里省略代码了
    if ( tr[x].rnd<tr[x].rnd )      //根据random的值,使y成为x的右子树,维护heap性质 
    {   
        tr[x].r=merge( tr[x].r,y );
        update( x ); return x;
    }
    else
    {
        tr[y].l=merge( tr[y].l,x );         //使x成为y的左子树 
        update( y ); return y;
    }
}

void split1( int now,int k,int &x,int &y )      //把一个Treap分成两树(按权值分)
{
    if ( now==0 ) 
    {
        x=y=0; return;
    }
    if ( tr[now].val<=k ) x=now,split1( tr[now].r,k,tr[now].r,y );      //now比k小,左子树+根节点→x,递归分割右子树
    else y=now,split1( tr[now].l,k,x,tr[now].l ); 
    update( x ); update( y ); 
} 

void split2( int now,int k,int &x,int &y )      //按size分
{
    update( now );
    if ( k<=tr[tr[now].l].size ) y=now,split2( tr[now].l,k,x,tr[now].l );
    else x=now,split2( tr[now].r,k-tr[tr[now].l].size-1,tr[now].r,y );
} 

void insert( int val )
{
    split1( root,val,x,y );     //先分成两棵树
    root=merge( merge( x,New(val) ),y );        //合并左树和新节点,合并左右两树 
}

void del( int val )
{
    split1( root,val,x,z ); split1( x,val-1,x,y );      //此时要删除的节点(val)为y的根节点
    y=merge( tr[y].l,tr[y].r ); //去除val的影响
    root=merge( merge( x,y ),z );  
} 

int Get_rank( int val )
{
    split1( root,val-1,x,y ); 
    int answer=tr[x].size;
    merge( x,y );
    return answer;
}

int Get_val( int rk )
{
    while ( 1 )
    {
        if ( k<=tr[tr[now].l].size ) now=tr[now].l;     //k比左树小,左树内部; 
        else
        {
            if ( k==tr[tr[now].l].size+1 ) return now;      //正好为根节点
            else k-=tr[tr[now].l].size+1,now=tr[now].r;     //在右子树中 
        }
    }
}

前驱:
1.以val-1为界限分割root为x,y
2.在x中Get_val( tr[x].size )
3.合并

后继:
1. 以val分割root为x,y
2.在y中Get_val(1)
3.合并

分离区间l—r
1. split2( root,r,x,y)
2. split2( x,l-1,a,b )
3. 最终操作序列为b

题目:POJ3580 SuperMemo




SXL
22天前

RT,还有吐槽的课表咋没更新QAQ

UPD 2020/5/8 13:26
y总终于更了QAQ



活动打卡代码 AcWing 1700. 子序列问题

SXL
30天前
/*
题意:给定正整数序列A1,……,An。定义f(l,r)表示Al~Ar中,不同的整数的个数
        求sum( sum(f(l,r)^2 | r=l~n)| l=1~n )
思路:
    设g(r)=sum( f(l,r)^2 | l=1~r ),ans=sum( g(r) | r=1~n )
    枚举r,用数据结构求g(r),复杂度O(nlogn)
    预处理一个last,last[i]=上一个等于ai的位置,不存在为0
    考虑从r推导至r+1
    g(r+1)-g(r)=2*sum( f(l,r) | l=last[r+1]+1~r+1 )+r+1-last[r+1]
    用线段树或者树状数组维护即可 
*/
#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) (x)&(-x)
using namespace std;
const int INF=0x3f3f3f3f,N=1e6+10;
const ll mod=1e9+7;
ll c1[N],c2[N];
int a[N],b[N],d[N],last[N],n;

ll get_sum( int x )
{
    ll res=0;
    for ( int i=x; i>0; i-=lowbit(i) )
        res+=c1[i]*(x+1)-c2[i];
    return res;
}

void add( int x,int d,int n )
{
    for ( int i=x; i<=n; i+=lowbit(i) )
        c1[i]+=d,c2[i]+=(ll)d*x;
}

int main()
{
    scanf( "%d",&n );
    for ( int i=1; i<=n; i++ )
        scanf( "%d",&a[i] ),b[i-1]=a[i];

    sort( b,b+n ); int m=unique( b,b+n )-b;
    for ( int i=1; i<=n; i++ )
    {
        a[i]=lower_bound( b,b+n,a[i] )-b;
        last[i]=d[a[i]]; d[a[i]]=i;
    }
    ll ans=0,now=0;
    for ( int i=1; i<=n; i++ )
    {
        now+=i-last[i]+2*( get_sum(i)-get_sum(last[i]) );
        now%=mod; ans+=now;
        add( last[i]+1,1,n ); add( i+1,-1,n );
    }

    printf( "%lld\n",ans%mod );

    return 0;
}


活动打卡代码 AcWing 1699. 涂色游戏

SXL
30天前
/*
题意:10^20个格子,p1的倍数染红色(含0),p2的倍数染蓝色(同),若都有就任意一种。在忽略掉所有未染色格子后,
    问是否存在方案使得没有k个连续的格子同色。 
思路:显然一个lcm是一个循环,只需要一个就够了。 设p1<p2。
    显然题意可以转化为两个p2之间有没有可能塞进k个p1,显然能用蓝色尽量蓝色。
    然而,后面的一段,p1的分布会产生错位,可能导致一段里红色变多。设最多能少能错位g个。 也就是p1x-p2y=g
    由裴蜀定理可知,g最小就是gcd(p1,p2) 
注意:开long long,特判p1=p2,k=1 
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;

ll gcd( ll x,ll y )
{
    return y ? gcd(y,x%y) : x;
}

bool check( ll p,ll q,ll k )
{
    if ( p>q ) swap( p,q );
    if ( k==1 ) return 0;
    if ( p==q ) return 1;
    ll g=gcd( p,q );
    return (q-1)/p<k && (q-1-g)/p+1<k;
}

int main()
{
    int T; scanf( "%d",&T );
    while ( T-- )
    {
        ll p,q,k; scanf( "%lld%lld%lld",&p,&q,&k );
        if ( check(p,q,k) ) printf( "Yes\n" );
        else printf( "No\n" );
    }
}