HDU4596 Yet another end of the world 扩张欧几里德性质

HDU4596 Yet another end of the world 扩展欧几里德性质

这题坑了,我真该吃翔啊,居然一开始方程设错了而且没有去想连列的问题,我真是坑货,做不出就该重新理一下嘛,操蛋,

题意:给了N组x,y,z然后 问你是否存在两个或者两个以上的id,是的 id%x的值在区间[y,z]之间,若有则输出Cannot Take off

否则你懂得


根据题意 那么  列出 :

a*x1  + y1 <= id <= a*x1 + z1

b * x2 + y2 <= id <= b*x2 + z2,

假设有解的话,那么这两个区间肯定有重复部分,,那么继续推得:

a*x1 <= b*x2 + z2 和 b *x2 + y2 <= a*x1 + z1

化简可以得到

a* x1 - b* x2 <= z2 - y1  1号式子

b * x2 - a*x1 <= z1 - y2   2号式子

为了统一 再把2号变成

a*x1 - b*x2 <= y2 - z1


然后看到这个应该就要想到扩展欧几里德,若存在非负的且不都为0整数a,b,必然存在整数对 x,y使得  gcd(a,b) = a*x + b*y,

应用到这道题目上也就是  要求  gcd(x1,x2) = a*x1 + (- b*x2)  这个式子存在解,这个式子的值同时又是  z2 - y1所以实际上就是转化成了

gcd(x1,x2)与 z2 - y1得有整数倍的关系 ,意思就是  (z2-y1)%gcd(x1,x2) == 0,注意是取模,竟然看到有篇题解写的是除号,做完想看看别人做法时看到这里坑了我一下,还以为我推的有问题呢,原来是他自己写错了,问题是居然另外有人的题解 直接复制了 他的解析,唉~~~~~

同时对于式子2我们也可以推到  (y2 - z1)%)gcd(x1,x2) == 0  这两个其中任意一个满足即可,区间覆盖部分 不用严格包含,语文不太好说不清楚,反正留给自己长脑子的

题目给出了N组,N的范围为1000,直接扫两层暴力来判断就可以了,


我的判断是否整除部分是:


int cal(int a,int b,int c) {
	if(c%a == 0 || b%a == 0)return 1;//不等式相等情况时的整除
	return 0;
}

其他人的题解判断部分是:

bool isok(int t,int le,int ri)  
{  
    int i,j;  
    if(le%t==0||ri%t==0) return true ;  
    if(le<0&&ri>=0) return true ;  
    if(ri/t-le/t>0) return true ;  
    return false ;  
}  

而且目前为止我看到的网上的题解的 所有人的判断部分 如出一辙啊,全都是如上述所示的那样,但是我少了下面那两个if判断过了,是题目数据太水了吗,下面两个判断我还这么没搞懂,是我这个弱菜漏了什么吗,路过有大神请教指点啊,


#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>

#define ll long long

#define eps 1e-8

#define inf 0xfffffff

const ll INF = 1ll<<61;

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;

const int N = 1000 + 5;

int x[N],y[N],z[N];

void init() {
	memset(x,0,sizeof(x));
	memset(y,0,sizeof(y));
	memset(z,0,sizeof(z));
}

int gcd(int a,int b) {
	return b==0?a:gcd(b,a%b);
}

int cal(int a,int b,int c) {
	if(c%a == 0 || b%a == 0)return 1;//不等式相等情况时的整除
	return 0;
}

int main() {
	int n;
	while(scanf("%d",&n) == 1) {
		init();
		for(int i=0;i<n;i++) 
			scanf("%d %d %d",&x[i],&y[i],&z[i]);
		bool flag = false;
		for(int i=0;i<n;i++) {
			for(int j=i + 1;j<n;j++) { 
				int tmp = gcd(x[i],x[j]);
				if(cal(tmp,z[j] - y[i],y[j] - z[i])) {
					flag = true;
				}
			}
		}
		if(flag)
			puts("Cannot Take off");
		else 
			puts("Can Take off");
	}
	return 0;
}