AGC057C 题解
DaiRuiChen007 · · 题解
Problem Link
题目大意
给定一个
0\sim 2^n-1 的排列p_i ,每次可以把所有数+1 后对2^n 取模或每个数异或上x ,构造一种操作方法,使得p_i=i 。数据范围:
n\le 18 。
思路分析
记
可以倒推证明:最终排列满足该性质,且对于两个低
那么说明原本的排列也必须满足
假如
那么我们只要清空每个
只需要一个数据结构维护全局
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
int a[1<<18],n,N;
int p[1<<18],q[1<<18],tg[18]; //ds
void init() {
for(int i=0;i<N;++i) {
for(int k=0;k<n;++k) p[i]=(p[i]<<1)|(a[i]>>k&1);
p[i]|=N;
}
}
void rev(int x) { //^x
for(int i=0;i<n;++i) if(x>>i&1) tg[i]^=1;
}
void add() { //+1
for(int i=0,u=1;i<n;++i) q[u]^=1,u=u<<1|(tg[i]^q[u]);
}
int qry(int u) {
int y=0,x=p[u];
for(int i=n-1;~i;--i) {
y|=((x&1)!=(q[x>>1]^tg[i]))<<i,x>>=1;
}
return y;
}
vector <int> opr;
signed main() {
scanf("%d",&n),N=1<<n;
int m=N/2;
for(int i=0;i<N;++i) scanf("%d",&a[i]);
init();
for(int i=0;i<m;++i) if(a[i]%m!=a[i+m]%m) return puts("No"),0;
for(int i=0;i<m;++i) {
int x=qry(i);
if(x&m) {
opr.push_back((N-1)^x),opr.push_back(-1);
rev((N-1)^x),add();
}
}
opr.push_back(qry(0)),rev(qry(0));
for(int i=0;i<N;++i) if(i!=qry(i)) return puts("No"),0;
printf("Yes\n%d\n",(int)opr.size());
for(int i:opr) printf("%d ",i); puts("");
return 0;
}