求N奇数阶幻方

1. 如果矩阵\{a_{ij}\}满足条件,那么对任意\alpha,\beta\in \mathbb{R},\{\alpha+\beta a_{ij}\}也满足条件。
证明显然。

n为奇数,我们现在构造一个n阶幻方包含0到n^2-1所有数
a_{ij}=x+n*y
这里x,y满足同余式
\begin{cases}
x+y = i + a\mod n\\
x + 2y = j + b\mod n
\end{cases}
a,b待确定。

由于该方程组的系数矩阵的行列式为1,所以对任意i,j有唯一解。我们接下来确定a,b:

首先验证每行每列的和均相等,即\frac{n(n^2-1)}{2}

由于对任意i,,当x取遍模n的剩余类时,也会取遍所有的剩余类

故每行的和为:(0+\cdots + n-1)+n*(0+\cdots +n-1) = \frac{n*(n-1)*(n+1)}{2}=\frac{n(n^2-1)}{2}
同理验证每列。

对于对角线:令b = n - 1, a = (n-1)/2,可以验证y = (n - 1)/2, x = i
所以其和为:n*(0 + ... n - 1) + n(n - 1)/2 = n(n-1)(n+1)/2 = n(n^2 - 1)/2

偶数不成立是因为, (n-1)/2不能整除。
==========
这种用同余式构造组合结构的方法很常见,比如拉丁方的构造、n皇后问题的构造等。


作者:Changlong Wu
链接:https://www.zhihu.com/question/30498489/answer/48393702
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 
 1 import java.util.Scanner;
 2 //奇数阶幻方的实现
 3 public class Main {
 4     //n为用户输入的n阶奇数幻方   n为奇数
 5     public static int[][] magicOdd(int n) {
 6         //构造一个(n+2)*(n+2)矩阵
 7         int[][] square = new int[n + 1][n + 1];
 8         int i = 0;
 9         int j = (n + 1) / 2;
10         //从第一行的中间那个数字(是1)开始填幻方
11         //n阶幻方一共有n*n个数字(从1~n*n)
12         //奇数阶幻方的实现算法
13         for (int key = 1; key <= n * n; key++) {
14             if ((key % n) == 1)
15                 i++;
16             else {      // //填充当前数的右上角那个数
17                 i--;
18                 j++;
19             }
20             if (i == 0) {      ////判断条件:若是在(n+2)*(n+2)阶方阵的第一行
21                 i = n;
22             }
23             if (j > n) {
24                 j = 1;
25             }
26             square[i][j] = key;
27         }
28 
29         //对(n+2)*(n+2)阶的方阵进行筛选出中间的n*n阶幻方
30 
31         int[][] matrix = new int[n][n];
32 
33         for (int k = 0; k < matrix.length; k++) {
34 
35             for (int l = 0; l < matrix[0].length; l++) {
36                 matrix[k][l] = square[k + 1][l + 1];
37             }
38         }
39         return matrix;
40     }
41     public static void main(String[] args) {
42         Scanner a = new Scanner(System.in);
43         int b = a.nextInt();
44         //b为用户输入的奇数
45         System.out.println();
46         int[][] magic = Main.magicOdd(b);
47         for (int k = 0; k < magic.length; k++) {
48             for (int l = 0; l < magic[0].length; l++) {
49                 System.out.print(magic[k][l] + "    ");
50             }
51             System.out.println();
52         }
53     }
54 }

 

posted @ 2017-12-18 19:53  ixummer  阅读(1065)  评论(0编辑  收藏  举报