1. 程式人生 > >【Atcoder - AGC027D】Modulo Matrix

【Atcoder - AGC027D】Modulo Matrix

@Modulo [email protected]


@題目描述 - [email protected]

Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 1100 points

Problem Statement
You are given an integer N.Construct any one N-by-N matrix a that satisfies the conditions below. It can be proved that a solution always exists under the constraints of this problem.

1≤a(i,j)≤10^15

a(i,j) are pairwise distinct integers.

There exists a positive integer m such that the following holds: Let x and y be two elements of the matrix that are vertically or horizontally adjacent. Then, max(x,y) mod min(x,y) is always m.

Constraints
2≤N≤500

Input
Input is given from Standard Input in the following format:
N

Output
Print your solution in the following format:
a(1,1)…a(1,N)

a(N,1) … a(N,N)

Sample Input 1
2
Sample Output 1
4 7
23 10

For any two elements x and y that are vertically or horizontally adjacent, max(x,y) mod min(x,y) is always 3.

@中文題意@

構造一個元素互不相同的N*N矩陣,矩陣元素為不超過10^15的正整數。使得對於矩陣中相鄰的兩個元素x,y, max

( x , y ) m o d    min ( x , y ) \max(x,y) \mod \min(x,y) 為一個正整數常數。

@分析@

假如沒有元素互不相同的限制,我們可以對矩陣黑白二染色,形成棋盤狀。然後在黑格里填N,白格里面填N+1。

那麼現在有了元素互不相同的限制,我們仍然可以沿用這樣一個染色思想:令(1,1)為黑格,交替染色,使得白格里的元素總大於它四周黑格的元素。並且為了簡化問題,不妨讓模數值為 1,這樣問題轉化為(白格元素值-1)是它四周黑格元素的公倍數。一樣為了簡化問題,我們令白格元素=四周黑格元素的LCM + 1。

構造思路出來了,但是還有一個很嚴重的問題:直接這樣構造是會超出題目所給的10^15的範圍。
【於是考場上我就想到這裡而已……QAQ】

我們給每一條黑格斜線定一個素數權值,給每一個黑格定權值為穿過它兩條斜線——自左上至右下一條,自右上至左下一條——的權值之積。這樣,每個白格的元素就為四個素數之積+1。

不難發現自右上至左下的斜線恰有N條,我們令這N條斜線的權值為第1~N個質數,令自左上至右下的斜線的權值為N+1開始的質數。

則白格的最大值為 499 500 999 1000 1 = 3559 3571 7907 7919 1 = 795 , 7926 , 4323 , 2737 1 7 1 0 1 4 1 第499個質數 * 第500個質數 * 第999個質數 * 第1000個質數 - 1= 3559 * 3571 * 7907 * 7919 - 1= 795,7926,4323,2737 - 1≈ 7*10^14 - 1

這樣就很完美了。

@程式碼@

QAQ實際上我自己都沒有完全過掉這道題……
不過如果米娜桑如果還有什麼問題的話,我也會盡力解疑的~
【UPD in 2018/9/22】發現像之前那麼寫的話會有兩個數相同……還真的要特判QWQ

#include<cstdio>
typedef long long ll;
const int MAXN = 500;
const int MAXM = 10000;
bool vis[MAXM + 5];
int prm[MAXM + 5], pcnt = 0;
ll GCD(ll x, ll y) {
	return y == 0 ? x : GCD(y, x%y);
}
ll LCM(ll x, ll y) {
	return x / GCD(x, y) * y;
}
void sieve() {
	for(int i=2;i<=MAXM;i++) {
		if( !vis[i] ) prm[++pcnt] = i;
		for(int j=1;i*prm[j]<=MAXM;j++) {
			vis[i*prm[j]] = true;
			if( i % prm[j] == 0 ) break;
		}
	}
}
ll Mat[MAXN + 5][MAXN + 5];
int main() {
	sieve(); int N;
	scanf("%d", &N);
	if( N == 2 ) {
		printf("4 7\n23 10\n");
		return 0;
	}
	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
			Mat[i][j] = 1;
	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
			if( (i & 1) == (j & 1) ) {
				Mat[i][j] = prm[(i + j) / 2] * prm[(i+N+1-j)/2 + N];
				Mat[i+1][j] = LCM(Mat[i+1][j], Mat[i][j]);
				Mat[i-1][j] = LCM(Mat[i-1][j], Mat[i][j]);
				Mat[i][j+1] = LCM(Mat[i][j+1], Mat[i][j]);
				Mat[i][j-1] = LCM(Mat[i][j-1], Mat[i][j]);
			}
	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
			if( (i & 1) != (j & 1) )
				Mat[i][j]++;
	for(int i=1;i<=N;i++) {
		for(int j=1;j<N;j++)
			printf("%lld ", Mat[i][j]);
		printf("%lld\n", Mat[i][N]);
	}
}

@[email protected]

就是這樣,新的一天裡,也請多多關照哦(ノω<。)ノ))☆.。~