【杂题题解】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;
}
posted @ 2026-03-12 20:11  chrispang  阅读(33)  评论(0)    收藏  举报