CF610C Harmony Analysis

CF610C Harmony Analysis

思路

提供一种不同的构造方法,这里以 \(k=4\) 举例。

下面将 * 表示成 0+ 表示成 1,则一个向量可以表示为一个二进制数,向量相乘即为两数异或和。

因为向量积为 \(0\),显然得到的答案中一半为 0,一半为 1,于是先构造出一个一半为 0,一半为 1 的数:

0000000011111111

对于每次操作,我们把它的一半 0 与一半 1 交换位置,直到不能交换:

0000000011111111
0000111100001111
0011001100110011
0101010101010101

将该表旋转 \(90°\),则可以发现该表即为 \(0\sim 2^k-1\) 的十进制数的二进制表示。

0000
0001
0010
0011
0100
0101
...

容易证明每个数的 01 的数量仍然相等,且若干数的异或和仍然满足该性质

根据该性质,我们给每个数一个二进制编号:

(0001)   0000000011111111
(0010)   0000111100001111
(0100)   0011001100110011
(1000)   0101010101010101

\(0\sim 2^k-1\) 的每个数都可以表示为该表若干个数的异或和,于是可以计算出该表,再通过枚举每个数的编号求异或和得出答案。

可以发现这种方法得到的答案跟构造类似 \(\begin{bmatrix} A & A\\ A & -A \end{bmatrix}\) 的矩阵得出的答案是一样的。

代码

#include <bits/stdc++.h>
using namespace std;
int k;
bitset<512> d[15];
signed main() {
	cin>>k;
	for(int s=0;s<(1<<k);s++)
		for(int i=0;i<k;i++)
			if(s&(1<<i)) d[i][s]=true;
	for(int s=0;s<(1<<k);s++){
		bitset<512> res;
		for(int i=0;i<k;i++)
			if(s&(1<<i)) res^=d[i];
		for(int i=0;i<(1<<k);i++)
			cout<<(res[i]?'*':'+');
		cout<<endl;
	}
	return 0; 
}
posted @ 2025-03-26 11:02  WuMin4  阅读(15)  评论(0)    收藏  举报