题目
你有一个微型处理器,处理器有N个寄存器,编号为1到N,每个寄存器用二进制存储一个32位无符号整数(取值范围为0到2^32-1)。存储器能执行以下操作:
指令 描述 Example
1 K M 把寄存器K里面的数字向右旋转M位,再把结果写进寄存器K。 00000000000000000010001111111011
→ (M = 1010) → 11111110110000000000000000001000
(十进制下: 9211 → (M = 10) → 4 273 995 784)
2 K L 把寄存器K和L中的值进行异或运算,结果输出到系统总线中。 00000000000000000000001111000111
XOR 00000000000001111100000000000111
= 00000000000001111100001111000000
(十进制下: 967 XOR 507 911 = 508 864)
如果有多种解,输出字典序最小的解(如果两组解的前K-1个寄存器值相同,第K个寄存器不同,则第K个寄存器的值较小的解字典序更小)。
这题我们可以将每个寄存器的每一位抽出来考虑相互的关系,对于旋转操作,我们可以维护起始指针位置来还原回去后一一对应考虑。
然后用并查集做。
由于会有后效性,而且不能保证字典序最小,我们不能通过一开始决定x属于1或属于0,但可以通过维护x与其并查集顶部位的数是否相同来做。
对于x和y间的关系,若x和y在同一个并查集里,那么若x与y不同,而x与并查集顶部相同,y与并查集顶部也相同,则输出nema(还有x与y相同,同理可推)
若x和y在不同并查集里,那么我们通过x与y的关系,以及x与其并查集顶部的关系,和y与其并查集顶部的关系,推得将两个并查集顶部合并时连边的权值,若为1,则说明两个顶部不同,为0则相同。(动手推一下)
这些权值在getfather时迭代加起来,得到x与顶部是否相同。(奇数为不同,偶数为相同)
最后求答案,从高位枚举,看一下其所在并查集是否已确定,确定了的话,直接按限制得出,反之为0,然后按限制强制将顶部赋值。
贴代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int n,m;
int fa[N*32][2],s[N];
long long help[32];
bool bz[N*32],ans[N*32];
bool p;
void pre(){
help[0]=1;
for (int i=1;i<32;i++)
help[i]=help[i-1]+help[i-1];
}
int get(int x){
int y;
if (fa[x][0]==x)return x;
y=fa[x][0];
fa[x][0]=get(fa[x][0]);
fa[x][1]=(fa[x][1]+fa[y][1])&1;
return fa[x][0];
}
void init(){
static int x,y,z;
static long long v;
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=32;j++)
fa[(i-1)*32+j][0]=(i-1)*32+j;
p=1;
for (int i=1;i<=m;i++){
scanf("%d %d %d",&x,&y,&z);
if (x==1)
s[y]=(s[y]+z)%32;
else{
scanf("%lld",&v);
for (int i=0;i<32;i++){
static bool e1,e2,e3;
static int xx,yy;
e1=v&help[i];
xx=(y-1)*32+s[y]+1;
yy=(z-1)*32+s[z]+1;
get(xx);
get(yy);
e2=(fa[xx][1]!=fa[yy][1]);
e3=(fa[xx][0]==fa[yy][0]);
if (e3&&e2!=e1)p=0;
else
if (!e3){
fa[fa[xx][0]][1]=(e2!=e1);
fa[fa[xx][0]][0]=fa[yy][0];
}
s[y]=(s[y]+1)%32;
s[z]=(s[z]+1)%32;
}
}
}
}
void write(){
static int x;
static long long y;
if (!p)printf("-1");
else
for (int i=1;i<=n;i++){
y=0;
for (int j=32;j;j--){
x=(i-1)*32+j;
if (!bz[x]){
get(x);
if (bz[fa[x][0]])
ans[x]=(ans[fa[x][0]]^fa[x][1]);
else
bz[fa[x][0]]=1,ans[fa[x][0]]=fa[x][1];
bz[x]=1;
}
y+=ans[x]*help[j-1];
}
printf("%lld ",y);
}
}
int main(){
pre();
init();
write();
return 0;
}