【杂题题解】P2284 [HNOI2003] 密室之门
P2284 [HNOI2003] 密室之门
题目大意
给定 \(T\) 个询问,每个询问给定 \(a_i\) 与 \(b_i\)。
对于每个询问,要求是否存在一个 \(x\) 满足 \((b_1+x)\bmod a_1=(b_2+x)\bmod a_2=\cdots=(b_n+x)\bmod a_n\)。
题目分析
转化题意,设 \(c_i=a_i-b_i\),问是否存在 \(x\) 满足:
\[\begin{cases}x\equiv c_1\pmod{a_1}\\x\equiv c_2\pmod{a_2}\\\dots\\x\equiv c_n\pmod{a_n}\end{cases}
\]
唉,这不是中国剩余定理吗?而且不用求 \(x\) 的具体值,只问有没有,那不就更好办了。
目前式子:
\[x\equiv c_1\pmod{a_1}\\x\equiv c_2\pmod{a_2}
\]
转换:
\[x=k_1\times c_1+a_1
x=k_2\times c_2+a_2
\]
继续转换:
\[k_1\times c_1+a_1=k_2\times c_2+a_2
\]
得:
\[k_1\times c_1+k_2\times (-c_2)=a_2-a_1
\]
使用扩展欧几里得求出 \(k_1'\times c_1+k_2'\times (-c_2) = \gcd(c_1,-c_2)\) 的解。
\[\text{若 } \gcd(c_1, -c_2) \nmid (a_2 - a_1) \text{,则无解。}
\]
到此结束,暴力遍历与判断即可。
代码实现
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 110;
int T, n;
int a[N], b[N];
int gcd(int x, int y) {
if (y == 0) return x;
return gcd(y, x % y);
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
b[i] = a[i] - b[i];
}
for (int i = 1; i <= n; i++) {
bool flag = 1;
for (int j = i + 1; j <= n; j++) {
if ((b[j] - b[i]) % gcd(a[i], a[j])) {
flag = 0;
break;
}
}
if (!flag) {
cout << "impossible\n";
return ;
}
}
cout << "possible\n";
}
int main() {
int T;
cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号