提出 #71436263


ソースコード 拡げる

#include <stdio.h>

int main(void) {
	int N;
	int i, j;
	if (scanf("%d", &N) != 1) return 1;
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			printf(" %d" + !j, (i * N + j + 1) ^ (N % 2 == 1 && i == N / 2 && (j == N / 2 || j == N / 2 - 1)));
		}
		putchar('\n');
	}
	return 0;
}

/*

1 2 3
4 5 6
7 8 9

みたいに、単純に順番に並べる
行:1個下に行くと N**2 増える
列:1個右に行くと N 増える

最初の行の合計は N*(N+1)/2
最後の列の合計は 最初の行の N 倍 = N*N*(N+1)/2
よって、最後の列は、最初の行から (N-1)*N*(N+1)/2 増えている

ぶつからないか調べる

def check(n):
    deltas = [n*n*k for k in range(n)] + [(n-1)*n*(n+1)//2-n*k for k in range(n)]
    return len(set(deltas)) == n * 2

all([check(n) for n in range(2, 51)])

→ False

all([check(n) for n in range(2, 51, 2)])

→ True

よって、N が偶数のときは、これでおk

def check2(n):
    deltas = [n*n*k for k in range(n)] + [(n-1)*n*(n+1)//2-n*k for k in range(n)]
    return len(set(deltas)) == n * 2 - 1

all([check2(n) for n in range(3, 51, 2)])

→ True

よって、N が奇数のとき、必ずちょうど1個だけ被っている
→ 多分真ん中だろう
→ 真ん中付近の要素を入れ替え、列の和を±1して、被らなくする

*/

提出情報

提出日時
問題 C - 陣法魔
ユーザ mikecat
言語 C23 (GCC 14.2.0)
得点 300
コード長 1389 Byte
結果 AC
実行時間 1 ms
メモリ 1668 KiB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 300 / 300
結果
AC × 3
AC × 10
セット名 テストケース
Sample 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt
All 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt, 01_random_00.txt, 01_random_01.txt, 01_random_02.txt, 01_random_03.txt, 01_random_04.txt, 01_random_05.txt, 01_random_06.txt
ケース名 結果 実行時間 メモリ
00_sample_00.txt AC 0 ms 1592 KiB
00_sample_01.txt AC 0 ms 1632 KiB
00_sample_02.txt AC 0 ms 1556 KiB
01_random_00.txt AC 0 ms 1592 KiB
01_random_01.txt AC 0 ms 1668 KiB
01_random_02.txt AC 1 ms 1576 KiB
01_random_03.txt AC 1 ms 1540 KiB
01_random_04.txt AC 0 ms 1620 KiB
01_random_05.txt AC 0 ms 1668 KiB
01_random_06.txt AC 0 ms 1668 KiB