纪念我人生中的第一发紫题!
本题中有两个操作,分别是① a i ← ⌊ a i 2 ⌋ a_i \leftarrow \lfloor \frac{a_i}{2} \rfloor ai←⌊2ai⌋ 和 ② a i ← a i × 2 a_i \leftarrow a_i\times2 ai←ai×2 ,求最少需要多少次才能使 A A A 集合和 B B B 集合中的元素相等
首先我们钦定 a = m a x A , b = m a x B a=max_A,b=max_B a=maxA,b=maxB (因为让我们求最小操作次数,所以我们贪心地想从最大值切入问题,为什么不从最小值的原因后边有)则有三种情况:
- a = b a=b a=b 此时不用消耗操作次数,直接消掉即可
- a > b a>b a>b 我们直接反手一个操作①
- a < b a<b a<b 这个时候此题最精髓的性质出现了:操作②是不是等价于将偶数的 b / 2 b/2 b/2,然后还能愉快的得出如果 b b b 是奇数的时候是无解的(这就是我们要从最大值开始贪心了)
一个下位紫,代码极短
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
int n,x,y,ans;
priority_queue<int> a,b;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&x),a.push(x);
for(int i=1;i<=n;++i) scanf("%d",&x),b.push(x);
while(!a.empty()){
x=a.top(),y=b.top();
a.pop(),b.pop();
if(x==y) continue;
ans++;
if(x>y){
a.push(x/2),b.push(y);
}if(x<y){
if(y&1) return puts("-1"),0;
else a.push(x),b.push(y/2);
}
}
printf("%d\n",ans);
return 0;
}