Prosjecni(构造)

题目大意:

让你构造一n*n矩阵使得每行平均值出现在该行,每列平均值出现在该列,且表中数字不同。无解输出-1
1 ≤ n ≤ 100 , 0 ≤ a [ i ] [ j ] ≤ 1 0 9 1\leq n\leq 100,0\leq a[i][j]\leq 10^9 1n100,0a[i][j]109

思路

首先我们可以发现奇数直接挨着排就可以排完,n=2输出-1
然后我们考虑偶数
[ 1 2 3 . . . n − 1 a . . . . . . . . . ] \left[ \begin{matrix} 1& 2 & 3 & ... & n-1&a\\ ... \\ ...\\ ...\\ \end{matrix} \right] 1.........23...n1a
我们让 n − 1 n-1 n1 为第一行平均数
那么 a = n ∗ ( n − 1 ) − n ∗ ( n − 1 ) 2 = n ∗ ( n − 1 ) 2 a=n*(n-1)-\frac{n*(n-1)}{2}=\frac{n*(n-1)}{2} a=n(n1)2n(n1)=2n(n1)
然后我们继续排:
[ 1 2 3 . . . n − 1 a 1 + a . . . 2 a 1 + 2 a . . . 3 a . . . 1 + ( n − 2 ) a . . . ( n − 1 ) a 1 + x . . . a + x ] \left[ \begin{matrix} 1& 2 & 3 & ... & n-1&a\\ 1+a&&&...&&2a \\ 1+2a&&&...&&3a\\ ...\\ 1+(n-2)a&&&...&&(n-1)a\\ 1+ x&&&...&&a+x\\ \end{matrix} \right] 11+a1+2a...1+(n2)a1+x23...............n1a2a3a(n1)aa+x
我们考虑怎么处理最后一排
我们只要保证 a [ n ] [ 1 ] a[n][1] a[n][1]合法就可以了
那么仿照之前的操作:
x = n ∗ ( n − 2 ) a − ( n − 2 ) ∗ ( n − 1 ) 2 a = ( n − 2 ) ∗ ( n + 1 ) 2 a = ( n − 2 ) ∗ ( n − 1 ) ∗ n ∗ ( n + 1 ) 4 x=n*(n-2)a-\frac{(n-2)*(n-1)}{2}a=\frac{(n-2)*(n+1)}{2}a=\frac{(n-2)*(n-1)*n*(n+1)}{4} x=n(n2)a2(n2)(n1)a=2(n2)(n+1)a=4(n2)(n1)n(n+1)
然后就结束了,右下角那个肯定没有超出范围

代码

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<bitset>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
	int f=1,x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return f*x;
}
#define MAXN 100
#define INF 0x3f3f3f3f
int hang[MAXN+5],lie[MAXN+5];
int main(){
	//freopen("prosjecni.in","r",stdin);
	//freopen("prosjecni.out","w",stdout);
	int n=read();
	if(n==2){
		puts("-1");
		return 0;
	}
	if(n&1)
		for(int i=1;i<=n;i++){
			for(int j=1;j<n;j++)
				printf("%d ",(i-1)*n+j);
			printf("%d\n",i*n);
		}
	else{
		int x=n*(n-1)/2;
		for(int i=1;i<n;i++){
			for(int j=1;j<n;j++)
				printf("%d ",j+(i-1)*x);
			printf("%d\n",i*x);
		}
		for(int j=1;j<n;j++)
			printf("%d ",j+(n+1)*(n-2)*x/2);
		printf("%d\n",n*(n-1)/2+(n+1)*(n-2)*x/2);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值