ARC176A 01 Matrix Again 题解
题意:给定 \(n\),以及 \(m\) 对 \((a_i,b_i)\),你需要构造一个 \(n \times n\) 的 \(01\) 矩阵使得每行每列都恰好有 \(m\) 个数为 \(1\),且 \((a_i,b_i)\) 的位置上的数必须为 \(1\)。
首先我们考虑 \(m=1\) 的情况,会发现最终的 \(1\) 的分布一定是形如一条斜线。
进而我们会发现如果选满足 \(i+j \equiv k \pmod{n}\) 的所有 \((i,j)\)(\(k\) 为一个定值,即形如一条斜线的点)填上 \(1\),那么恰好满足每行每列都有一个数为 \(1\)。因为题目要求每行每列都恰好有 \(m\) 个数为 \(1\),于是我们选 \(m\) 个不同的 \(k\) 即可。但是题目还要求了 \((a_i,b_i)\) 必须为 \(1\),所以对于每一个 \(k=(a_i+b_i) \bmod n\) 都必须选。因为输入的 \((a_i,b_i)\) 为 \(m\) 个,所以必须选的 \(k\) 不超过 \(m\) 个,一定有解。其余的 \(k\) 随便选即可。时间复杂度 \(O(nm)\)。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 2e5 + 10;
int n,m,sum;
bool vis[MAXN];
signed main() {
cin >> n >> m;
for(int i = 1,a,b;i <= m;i++) {
cin >> a >> b;
if(!vis[(a + b) % n])
vis[(a + b) % n] = 1,sum++;
} printf("%lld\n",n * m);
for(int i = 0;i < n;i++) {
if(vis[i] || sum < m) {
if(vis[i] == false) sum++;
for(int j = 1;j <= n;j++)
printf("%lld %lld\n",j,(i - j + 2 * n - 1) % n + 1);
}
} return 0;
}