先说一下题意吧:有 T 组数据,每组数据包含 x,y,a,b,c,d 六个数,我们可以给 x 进行无数次操作:令 x\leftarrow x \operatorname{AND} a 或者 令 x\leftarrow x \operatorname{OR} b 的操作,第一种操作所需要的代价为 c,第二种操作所需要的代价为 b,你需要求出将 x 变为 y 的最小代价,如果做不到,输出 -1。
就是这样。
思路
这道题可以有多种情况,我们可以进行分类讨论:
有的童鞋可能会问了,有可能使 x 变为 y 需要多次运算,那该怎么办。
咳咳,这种情况是可以的,但是这样肯定不会使代价小于前面说的四种操作。
不妨用 1 15 2 14 3 5 模拟一下。
这道题考验的是二进制,所以先把 x,y,a,b 转化为二进制计算。
$y$ 用二进制表示是 $111$;
$a$ 用二进制表示是 $010$;
$b$ 用二进制表示是 $101$。
用 $x\operatorname{AND} a$ 的操作,使得 $x$ 变为二进制下的 $000$,如果再使用一次,结果依旧是 $000$。
用 $x\operatorname{OR} b$ 的操作,使得 $x$ 变为二进制下的 $101$,如果再使用一次,结果依旧是 $101$。
很明显,连续多次的同一个操作,答案都会相等,所以不会有同一操作连续两次进行的情况。
童鞋:那如果不连续呢?
不连续的情况会有两种:
- 操作一后操作二再是操作一,事实上这个做出来的答案等于操作二再操作一。
- 操作二后操作一再是操作二,这个做出来的答案等于操作一再操作二。
可以发现能出现的情况只有四种能得到代价最小值。
注意还要特判 $x=y$,这种情况不需要任何操作,直接输 $0$ 即可。
## AC CODE
```c
#include<bits/stdc++.h>
using namespace std;
int n;//10 的 5 次方不用 long long。
int x,y,a,b;//2 的 30 次方。
long long minn;//记录代价最小值,最大可以是两个二的 30 次方的和,不开 long long 见祖宗。
long long c,d;//需要和 minn 比较,所以也要开 long long。
int main(){
cin>>n;
while(n--){
minn=1000000005;//比较大的值,用来存最小代价。
cin>>x>>y>>a>>b>>c>>d;
if(x==y){//特判。
cout<<0<<endl;
continue;
}
if(((x&a)|b)==y||((x|b)&a)==y){//注意要用括号括起来,不然会出问题。
minn=c+d;
}
if((x&a)==y){
minn=min(minn,c);
}
if((x|b)==y){
minn=min(minn,d);
}
if(minn==1000000005){//如果无解输出 -1。
cout<<-1<<endl;
continue;
}
cout<<minn<<endl;
}
return 0;
}
```
>请勿抄袭题解。这会失去学术诚信,同时浪费洛谷评测资源。如果被发现抄题解,可能会被处以棕名惩罚或者被封号。——摘自《洛谷新用户必读》