P9890 [ICPC2018 Qingdao R] Tournament 題解

薛儒浩發表於2024-10-21

P9890 [ICPC2018 Qingdao R] Tournament

題目傳送門

更好的閱讀體驗

一道找規律的思維題。

前置知識 \(lowbit\)

\(lowbit\) 是指獲取一個二進位制數中最右邊的 \(1\) 所對應的數值。

具體地, \(lowbit\) 可以透過對一個數取反然後加 \(1\) ,再與原數進行按位與的方式來實現。

int lowbit(int x) {
	return x&-x;
}

例子:對於 \((11010)_2\) (十進位制下為 \(26\) )來說,它的 \(lowbit\)\((10)_2\) (十進位制下為 \(2\) ),即 \(lowbit(26)=2\)

Solve

其實題意說得已經非常清楚了,我們可以將騎士分成二冪次組,構造打出迴圈賽日程表,透過找規律不難發現最多進行 \(lowbit(n)-1\) 場比賽,最後依次輸出即可。

And 至於為什麼最多進行 \(lowbit(n)-1\) 場比賽,我想到了一段不嚴格的文字證明:在比賽中,每場比賽都會消除掉一個騎士,所以在給定人數為 \(n\) 時,總的比賽次數就是將騎士數縮減為 \(1\) 的過程。最多的比賽發生在每輪都儘可能減少最少人數的情況下,即每次比賽中淘汰 \(lowbit(n)\) 個騎士。因此,總的比賽次數為 \(lowbit(n) - 1\)

Code

#include <bits/stdc++.h>
#define N 2005

int A[N][N];
int T,n,k;

int lowbit(int x) {
	return x & -x;
}

int main() {
	A[1][1]=1;
	for(int k = 1; k < 1024; k *= 2) {
		for(int i = 1; i <= k; i++) {
			for(int j = 1; j <= k; j++) {
				A[i + k][j + k] = A[i][j];
				A[i][j + k]=A[i + k][j] = A[i][j] + k;
			}
		}
	}
	std::cin>>T;
	while(T--) {
		std::cin>>n>>k;
		if(k > lowbit(n) - 1) {
			std::cout<<"Impossible";
			puts("");
			continue;
		}
		for(int i = 2; i <= k + 1; i++) {
			for(int j = 1; j <= n; j++) {
				std::cout<<A[i][j]<<" ";
			}
			puts("");
		}
	}
	return 0;
}

over~

相關文章