P8348 题解
题目传送门
这题怎么是黑题??
关键点:所有的元素都需要大于等于
由于如果同时考虑相邻两项做加法和减法决策太多(你 TLE
了还能有决策?),应该简化决策。
很明显,题目给出的元素下限就是一个“风向标”,告诉你要化成只做减法(加法都没边界,不知道得加到什么时候)。
可以假设需要使用加法才能判断是否可以位于一个“
相信规则已经很明显了,
设数对
由于对于第一次加法得到的数
对于其他情况,它的上一个数一定是
可以发现,每进行两次减法,
因此证明了在原数对基础上使用加法后,若能使得读入的两个数对相同,使用减法也一定能达到相同的结果(把加法操作会原数对后再继续减法就相当于在原数对上使用减法),因此,我们可以只使用减法。
使用减法的朴素算法是
不妨设数对
对这个数对进行减法:
可以发现
减法终止条件:
AC code:
#include<bits/stdc++.h>
using namespace std;
int k;
void getmin(int &a,int &b) // 要修改具体值,必须传引用
{
while(true)
if(a < b)
{
int now = (b-k)/a; // 大于k的部分还能减多少次
if(!now) return; // 减不了也退出
b -= now * a;
if(now % 2 == 1) swap(b,a); // 奇数交换偶不换
}
else if(a > b)
{
int now = (a-k)/b; // 大于k的部分还能减多少次
if(!now) return; // 减不了也退出
a -= now * b;
if(now % 2 == 1) swap(a,b); // 奇数交换偶不换
}
else return; // 相等无法变换,退出
}
int main()
{
int t;
cin >> t;
while(t--)
{
int x,y,xx,yy;
scanf("%d%d%d%d%d",&x,&y,&xx,&yy,&k);
if(k > xx || k > yy || k > x || k > y) // 不满足题目限制
{
printf("no\n");
continue;
}
getmin(x,y); getmin(xx,yy); // 全部转化成两个数都大>=k的最小数对
if(xx == x && yy == y) printf("yes\n"); // 同一个最小数对,满足要求
else printf("no\n");
}
}