1. 程式人生 > 實用技巧 >Zoj 4063(構造題 思維題)

Zoj 4063(構造題 思維題)

const int MAX_N = 1e3 + 50;

int N, K;
int mat[MAX_N][MAX_N];

void work(int len) {
	if (2 * len > MAX_N)//1024即可
		return;
	for (int i = 1; i <= len; i++) {
		for (int j = 1; j <= len; j++) {
			mat[i + len][j] = mat[i][j] + len;//構造左同大小矩陣
			mat[i + len][j + len] = mat[i][j];//構造斜左下同大小矩陣
			mat[i][j + len] = mat[i][j] + len;//構造下同大小矩陣
		}
	}
	work(2 * len);//擴大規模
}

void init() {
	mat[1][1] = 1; mat[1][2] = 2;
	mat[2][1] = 2; mat[2][2] = 1;
	work(2);
}

bool check() {//檢查前k行是否有出現大於N的數出現
	for (int i = 2; i <= K + 1; i++) {
		for (int j = 1; j <= N; j++) {
			if (mat[i][j] > N) {
				return false;
			}
		}
	}
	return true;
}

int lowbit(int x) {
	return x & (-x);//-x = ~x + 1
}

int main() {
	//while (~scanf("%d", &N)) 
		//printf("%d\n", lowbit(N));
	init();
	int T;
	cin >> T;
	while (T--) {
		scanf("%d%d", &N, &K);
		//bool ok = check();
		if (K >= lowbit(N)) {//直接用lowbit判斷
			puts("Impossible");
			continue;
		}
		for (int i = 2; i <= K + 1; i++)
			for (int j = 1; j <= N; j++)
				printf("%d%c", mat[i][j], j == N ? '\n' : ' ');
	}
}

問題轉化為找到m個二階置換{f_i},使得對於任意i!=j都有f_i(a)!=f_j(a)且f_i(f_j(a))=f_j(f_i(a))。
再想一想異或的性質。?
真的牛

int n, m, k;
int main(){
	int T, cas = 1;
	scanf("%d", &T);
	while (T--){
		scanf("%d%d", &n, &m);
		if (m >= (n & (-n))) { puts("Impossible"); continue; }
		for (int j = 1; j <= m; j++)
			for (int i = 0; i < n; i++)
				printf("%d%c", (i ^ j) + 1, i == n - 1 ? '\n' : ' ');
	}
	return 0;
}