Description
追风的少年基XX为了赶上风速,他亲自打造了一个坐骑,他的坐骑拥有土豪级别的两个键帽,分别为加速按钮和减速按钮。那么问题来了,他每按一次加速按钮,可以给他的坐骑增加a的速度,每按一次减速按钮,他的坐骑速度会减少b,当速度减少到0的时候,不再减速,但依然可以继续按减速按钮。他坐骑现在的速度为s,但必须达到速度t(必须等于),才能赶上风的速度。还有个更严重的问题,他必须按n次按钮,不然他坐骑上的GTX1080战术核显卡是会BOOM的……基XX想知道,在不引爆显卡的情况下,能不能赶上风的速度。
Input
输入一排,分别为描述中所叙述的n,s,t,a,b。其中1≤n≤109 0≤s,t≤109 1≤a,b≤109
Output
输出一行,如果基XX能赶上风的速度,输出“YES”,否则输出“BOOM”.
4 2 3 3 3 2 1 100 2 2
YES BOOM
分析:
这个题目可以分为两种情况,
第一种就是在追逐过程中不会降到0,换句话意思就是说存在两个正整数x,y使得 ax+by= t-s 成立并且有 x + y = n,这样两个二元一次方程可以解出x,y如果有整数解,那么说明YES,否则判断第二种情况。
第二种就是在追逐过程中会先降到0,然后再0的时候继续反复减速(也可以不继续减速)然后再加速到 t,这样的情况我们就分为前后两段,第一段是减速到0,很显然这一个过程至少需要 sub(s/b) 次。sub(a)表示对a向上取整。因为速度减为0之后我们可以反复0处通过减速来浪费次数,所以我们要在n - sub(s/b) 次数内 从0上升到t.这样题目就转化为为.
ax+by = t, 并且 x>=0 && y>=0 求x+y的最小值,如果x+y的最小值 小于 n - sub(s/b) 就说明YES,否则就NO. 这里因为 t 的范围很大所以要使用拓展欧几里得来求解。循环判断要超时。
ax+by = t 显然 t % gcd(a,b) == 0 才有解。令 t / gcd = c . 那么 求得一组特殊解 x0a + y0b = gcd .那么 cx0 ,cy0 就是 ax+by = t 的一组特解。那么通解是什么呢?
x = cx0 + b/gcd * m
y = cy0 - a/gcd * m
然后就可以用这两个式子来求得x,y。
代码:
#include <stdio.h>
#include <string.h>
long long MAX(long long a,long long b)
{
return a>b?a:b;
}
long long MIN(long long a,long long b)
{
return a<b?a:b;
}
long long e_gcd(long long a,long long b,long long &x,long long &y)
{
if(b == 0){
x = 1;
y = 0;
return a;
}
long long ans = e_gcd(b,a%b,y,x);
y = y - a/b*x;
return ans;
}
bool tz_gcd(long long a,long long b,long long c,long long& x,long long& y)
{
long long gcd;
gcd = e_gcd(a,b,x,y);
if(c % gcd != 0)
{
return false;
}
else
{
x = c / gcd * x;
y = c / gcd * y;
if( x > 0 && y < 0 )
{
long long t = 0;
t = x / (b/gcd);
t = MIN(t,-y/(a/gcd));
x = x - b/gcd * t;
y = y + a/gcd * t;
}
else
{
long long t = 0;
if( x < 0)
{
if( (-x * gcd) % b == 0) t = (-x*gcd)/b;
else t = (-x * gcd)/b + 1;
}
if( y > 0)
{
if( (y * gcd) % a == 0 ) t = MAX(t,(y*gcd)/a);
else t = MAX(t,(y*gcd)/a+1);
}
x = x + b/gcd * t;
y = y - a/gcd * t;
}
}
return true;
}
bool Jianjie(long long n,long long s,long long t,long long a,long long b)
{
long long c;
if( s % b == 0) c = s / b;
else c = s / b + 1;
long long x,y;
if(!tz_gcd(a,b,t,x,y)) return false;
y = -y;
if( c + x + y <= n) return true;
return false;
}
int main()
{
long long n,s,t,a,b;
while(scanf("%lld%lld%lld%lld%lld",&n,&s,&t,&a,&b)!=EOF)
{
if((t + n * b - s) % (a+b) == 0)
{
printf("YES\n");
continue;
}
if(Jianjie(n,s,t,a,b))
{
printf("YES\n");
continue;
}
printf("BOOM\n");
}
return 0;
}