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;
}
posted @ 2024-04-29 14:39  Creeper_l  阅读(22)  评论(0编辑  收藏  举报