NJUST 1747 Yet another end of the world(13年南京邀请赛-K题-数学)

题目链接:Click here~~

题意:

有 n 个三元组 {x,y,z},问是否存在一个任意数 num 和一对 i,j,使 num % x[i] 和 num% x[j] 的值分别落在对应的区间 [ y[i] , z[i] ] 和[ y[j] , z[j] ] 中。

解题思路:

由于 n 是 1e3,所以可以直接枚举 i,j,关键是如何判断他们是否存在满足这样要求的值。

不妨设 num % x[i] = a , num % x[j] = b,则 num = k1 * x[i] + a , num = k2 * x[j] + b 。

将 num 消掉,可以得出 k1 * x[i] + a = k2 * x[j] + b 从而 x[i] * k1 - x[j] * k2 = b - a。

发现这是一个不定方程,方程有解当且仅当 (b-a) % gcd(x[i],x[j]) = 0。

由于 a , b 的值都必须属于对应的 [y,z] 区间,所以可以得到 b-a 的范围。

得出范围后,只需要判断这个范围中是否存在 % gcd(x[i],x[j]) = 0 的值即可。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;

const int N = 1005;

int x[N],a[N],b[N];

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

bool meet(int i,int j)
{
    int l = a[j] - b[i];
    int r = b[j] - a[i];
    int d = gcd(x[i],x[j]);
    if(l%d==0 || r%d==0)
        return true;
    else
        return l/d != r/d;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
            scanf("%d%d%d",&x[i],&a[i],&b[i]);
        bool ok = true;
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
                if(meet(i,j))
                {
                    ok = false;
                    goto end;
                }
end:    puts(ok?"Can Take off":"Cannot Take off");
    }
    return 0;
}


你可能感兴趣的:(NJUST 1747 Yet another end of the world(13年南京邀请赛-K题-数学))