第一行输入一个整数
,表示测试用例数;
每个测试用例输入格式如下:
第一行输入一个整数
;
第二行输入
个整数
;
第三行输入
个整数
;
保证所有测试用例中
。
对于每个测试用例,输出一行整数——使
与
同构的最少操作次数。
2 3 4 1 2 2 2 1 3 7 3 5 3 3 5
2 1
初始时,
;
对
中元素
执行一次变换,得到
,此时
;
对
中一个元素
执行一次变换,得到
,此时
;
此时两数组的元素可以一一匹配,故最少操作数为
。
在第二个测试用例中:仅需将
中的
变换为
,得到
,与
相同,操作数为
。
#include<bits/stdc++.h>
using namespace std;
int cntOfOne(long long num) {
int cnt = 0;
//需要确保num的二进制不会有64个1
while (num) {
if (num & 1) {
cnt++;
}
num = num >> 1;
}
return cnt;
}
int main() {
//所有数 -> [1,63] -> [1,6] -> [1,2]
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;int tt=t;
while (tt--) {
int n;
cin >> n;
vector<long long> num1(n, 0);
vector<long long> num2(n, 0);
for (int i = 0; i < n; i++) {
cin >> num1[i];
}
for (int i = 0; i < n; i++) {
cin >> num2[i];
}
int ans = 0;
int cnt[64]; memset(cnt, 0, sizeof(cnt));
unordered_map<long long, int> mp;
for (int i = 0; i < n; i++) {
mp[num1[i]]++;
mp[num2[i]]--;
}
for (auto num : mp) {
if (num.second > 0) {
if (num.first > 63) {
ans+=num.second;
cnt[cntOfOne(num.first)]+=num.second;
}
else {
cnt[num.first]+= num.second;
}
}
else if(num.second < 0){
if (num.first > 63) {
ans+=(-num.second);
cnt[cntOfOne(num.first)]+= num.second;
}
else {
cnt[num.first]+= num.second;
}
}
}
//if(t==11){ for(auto n:cnt)cout<<n<<" ";cout<<endl;}
int cnt2[7]; memset(cnt2, 0, sizeof(cnt2));
for (int i = 1; i < 64; i++) {
if (cnt[i] > 0) {
if (i > 6) {
cnt2[cntOfOne(i)]+=cnt[i];
ans+=cnt[i];
}
else {
cnt2[i]+=cnt[i];
}
}
else if (cnt[i] < 0) {
if (i > 6) {
cnt2[cntOfOne(i)]+=cnt[i];
ans+=(-cnt[i]);
}
else {
cnt2[i]+=cnt[i];
}
}
}
//for(auto n:cnt2)cout<<n<<" ";cout<<endl;
int cnt3[3] = { 0,0,0 };
for (int i = 1; i < 7; i++) {
if (cnt2[i] > 0) {
if (i > 2) {
ans += cnt2[i];
cnt3[cntOfOne(i)] += cnt2[i];
}
else {
cnt3[i] += cnt2[i];
}
}
else if (cnt2[i] < 0) {
if (i > 2) {
ans += (-cnt2[i]);
cnt3[cntOfOne(i)] += cnt2[i];
}
else {
cnt3[i] += cnt2[i];
}
}
}
//for(auto n:cnt3)cout<<n<<" ";cout<<endl;
ans += abs(cnt3[1]);
cout << ans << endl;
}
}
// 64 位输出请用 printf("%lld") #include <bits/stdc++.h>
using namespace std;
unsigned long long popcount(unsigned long long x) { return __builtin_popcount(x); }
unsigned long long maxx=0;
unsigned long long process(unordered_map<unsigned long long,unsigned long long>& a, unordered_map<unsigned long long,unsigned long long>& b, unsigned long long thread){
// 匹配减少
for(auto it = a.begin(); it != a.end(); ) {
unsigned long long num = it->first, cnt = it->second;
if(b.count(num)){
unsigned long long minus = min(cnt, b[num]);
it->second -= minus;
b[num] -= minus;
if(b[num] == 0) b.erase(num);
if(it->second == 0) it = a.erase(it); // 使用迭代器
else ++it;
} else {
++it;
}
}
unsigned long long res = 0;
// popcount操作
for(auto it = a.begin(); it != a.end(); ) {
unsigned long long num = it->first, cnt = it->second;
if(num >= thread){
res += cnt;
it = a.erase(it); // 使用迭代器
unsigned long long newNum = popcount(num);
a[newNum] += cnt; // 可以直接累加
maxx=max(maxx,newNum);
} else {
++it;
maxx=max(maxx,num);
}
}
for(auto it = b.begin(); it != b.end(); ) {
unsigned long long num = it->first, cnt = it->second;
if(num >= thread){
res += cnt;
it = b.erase(it); // 使用迭代器
unsigned long long newNum = popcount(num);
b[newNum] += cnt;
maxx=max(maxx,newNum);
} else {
++it;
maxx=max(maxx,num);
}
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
unsigned long long t;
cin >> t;
while(t--) {
unsigned long long n;
cin >> n;
unordered_map<unsigned long long,unsigned long long> cntA,cntB;
maxx=-1;
for(unsigned long long i=0;i<n;++i){
unsigned long long temp;
cin>>temp;
if(cntA.count(temp)){
cntA[temp]++;
}else{
cntA[temp]=1;
}
maxx=max(maxx,temp);
}
for(unsigned long long i=0;i<n;++i){
unsigned long long temp;
cin>>temp;
if(cntB.count(temp)){
cntB[temp]++;
}else{
cntB[temp]=1;
}
maxx=max(maxx,temp);
}
unsigned long long ops = 0;
// 去重
vector<unsigned long long> threads={21,5,3,2,0};
for(unsigned long long i:threads){
if(maxx>=i){
maxx=0;
ops += process(cntA,cntB,i);
}else{
continue;
}
}
cout << ops << "\n";
}
}