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~