题意
(n imes n) 的矩阵,要求 (forall k in[1,n]) ,第 (k) 行和第 (k) 列加起来是 (1...2n-1)
求出一种可行方案,或输出无解。
题解
(大多是抄的PPT,存个档)
考虑每个位置对哪些目标产生贡献,对角线上的贡献一次,其他的贡献两次。
若 (n) 为奇数,(2n - 1) 个数都要贡献奇数次,说明每个数都需要有一个在对角线上,但对角线上只有 (n) 个位置,要求 (2n-1le n),所以除了 (n = 1) 都必然无解。
(n) 为奇数时,考虑把所有的 (2n-1) 放在对角线上,剩下的位置对于两个目标点连边,构成了一张完全图(有向图)。
对于完全图的所有边,每个边着一种颜色,共有 (2n-2) 种颜色,完全图共有 (n) 个点。要求每个点相连的任意两条边颜色不同。
所有的((i,j)) 和 ((j,i)) 很烦 ((i<j)) ,反正他们永远都一起出现,干脆将他们合为一条边,让((j,i)=(i,j)+n-1),变成无向完全图,有 (n-1) 种颜色,(n) 个点。
循环赛:两两之间都打两场。
转化为偶数大小的循环赛划分(这个不太懂啥意思,大致就是上面说的要求的东西...好像网上也没有看到这样叫的)
代码
好难写,,
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mkp make_pair
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
int n, ans[510][510];
int change(int x){
x--; if(x == 0) x = n;
return x;
}
int change2(int x){
x++; if(x == n + 1) x = 1;
return x;
}
int main(){
//用n-1种颜色对n个点的完全图进行着色
scanf("%d", &n);
if(n == 1){
puts("Yes
1"); return 0;
}
if(n % 2){
puts("No"); return 0;
}
puts("Yes");
for(int i = 2; i <= n; i++){
//标杆指向(1, i),颜色为i-1
// cout<<"calc: "<<i<<endl;
ans[1][i] = ans[i][1] = i - 1;
int qwq = i * 2;
for(int j = 1, k = i, l = i; j <= n / 2 - 1; j++){
k = change(k); if(k == 1 || k == i) k = change(k); if(k == 1 || k == i) k = change(k);
l = change2(l); if(l == 1 || l == i) l = change2(l); if(l == 1 || l == i) l = change2(l);
// cout<<k<<" "<<l<<endl;
ans[k][l] = ans[l][k] = i - 1;
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++){
if(i > j) ans[i][j] += n - 1;
if(i == j) ans[i][j] = 2 * n - 1;
printf("%d%c", ans[i][j], (j < n) ? ' ' : '
');
}
return 0;
}