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
...
容易证明每个数的 0 与 1 的数量仍然相等,且若干数的异或和仍然满足该性质。
根据该性质,我们给每个数一个二进制编号:
(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;
}

浙公网安备 33010602011771号