我们反着想,将原来的第n-1次操作变为第一次选两个点,满足|a-b|可以整除n-1。因为可以整除n-1,所以|a-b|模n-1的余数应该是0,也就是说a模n-1的余数应该等于b模n-1的余数,这样就是合法点对。因为现在有n个点,然后n个点对n-1取模,根据抽屉原理,一定有两个数的余数相等,那么我们就取这两个数连接一条边,然后因为这两点已经连接一条边了,我们直接随便删一个点,那下一次操作就是n-1个点里找两个点模n-2的余数相等,根据抽屉原理,肯定存在。
iota函数是给区间赋值以value为起点的公差为1的等差数列
题解的代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int tests;
cin >> tests;
while (tests--) {
int n;
cin >> n;
vector<int> a(n);
for (auto& i : a) cin >> i;
vector<int> pos(n);
iota(pos.begin(), pos.end(), 0);
vector<pair<int, int>> ans;
for (int i = n - 1; i; --i) {
vector<int> occ(i, -1);
for (auto j : pos) {
if (occ[a[j] % i] != -1) {
ans.emplace_back(j, occ[a[j] % i]);
pos.erase(find(pos.begin(), pos.end(), j));
break;
}
occ[a[j] % i] = j;
}
}
reverse(ans.begin(), ans.end());
cout << "YES\n";
for (auto [x, y] : ans) cout << x + 1 << ' ' << y + 1 << '\n';
}
}