描述
o Slavko 很无聊,所以他把正整数填到 N N*N 的方阵中。
如果他填出来的方阵满足以下条件,他会特别高兴:
● 每行中的数字的平均值是一个位于同一行的整数。
● 每列中的数字的平均值是一个位于同一列的整数。
● 表中的所有数字都不同。
帮助 o Slavko 找到一种会让他开心的填法。
输入
第一行输入包含整数 N N (1 1 ≤N N ≤ 100
输出
输出 N N 行 , 每行输出 N N 个由空格分隔的整数 。 令第 i i 行中的第 j j 个数字对应
于 于 o Slavko 将在方阵的第 i i 行第 j j 列写下的值。
所有数字必须大于 0 0 且小于 10
9 9 。
如果有多个解决方案,则输出任意一个。
如果没有任何解决方案,则输出 -1
样例输入 1
3
样例输出 1
1 2 3
4 5 6
7 8 9
样例输入 2
2
样例输出 2
-1
思路
如果n为奇数 则按早从左往右 从上至下的方式填一个不断递增的数
否则当n为偶数时 第一列
1 | 2 | 3 | ... | n-1 | (frac{(n-1)n}{2}) |
---|---|---|---|---|---|
1+(frac{(n-1)n}{2}) | 2+(frac{(n-1)n}{2}) | 3+(frac{(n-1)n}{2}) | 4+(frac{(n-1)n}{2}) | ||
1+2*(frac{(n-1)n}{2}) | |||||
1+3*(frac{(n-1)n}{2}) | |||||
1+(n-2)*(frac{(n-1)n}{2}) | |||||
x |
以1+(n-2)*(frac{(n-1)n}{2})为第一列平均数 可求x
然后使得最末行与倒数第二行的差等
代码
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 101;
int a[MAXN][MAXN];
int main()
{
//freopen("prosjecni.in","r",stdin);
//freopen("prosjecni.out","w",stdout);
int n,i,j;
scanf("%d",&n);
if(n & 1)
{
int ans = 0;
for(i = 1;i <= n;i++)
{
for(j = 1;j <= n;j++)
{
printf("%d",++ans);
if(j != n) printf(" ");
}
if(i != n)
printf("
");
}
} else{
if(n == 2)
{
printf("-1");
return 0;
}
int delta,x = n * (n - 1) / 2;
for(i = 1;i <= n;i++) a[1][i] = i;
a[1][n] = x;
for(i = 2;i < n;i++)
for(j = 1;j <= n;j++)
a[i][j] = a[i - 1][j] + x;
a[n][1] = a[n - 1][1] * n - (1 + a[n - 1][1]) * (n - 1) / 2;
delta = a[n][1] - a[n - 1][1];
for(i = 2;i <= n;i++) a[n][i] = a[n - 1][i] + delta;
for(i = 1;i <= n;i++)
{
for(j = 1;j <= n;j++)
{
printf("%d",a[i][j]);
if(j != n) printf(" ");
}
if(i != n)
printf("
");
}
}
return 0;
}