P16519 [GKS 2015 #E] Robot Rock Band 题解

题目大意

有 \(T\) 组测试用例,每组测试用例给定四个列表 \(A\),\(B\),\(C\),\(D\),每个列表包含 \(N\) 个数字,问有多少种方式从四个列表中各选一个数使异或和为 \(K\)。

思路分析

这题看似要用 \(O(n^4)\) 的时间复杂度过,但这样会超时,所以我们要另寻出路。

我们设从 \(A\) 列表拿的数为 \(a\),从 \(B\) 列表拿的数为 \(b\),从 \(C\) 列表拿的数为 \(c\),从 \(D\) 列表拿的数为 \(d\),那么 \(a\bigoplus b\bigoplus c\bigoplus d=K\),然后我们将这个式子转移一下就变成这样 \(a\bigoplus b=K\bigoplus c\bigoplus d\)。

这样问题就简单多了,相当于求从 \(A\),\(B\),\(C\),\(D\) 中各拿一个数,使 \(a\),\(b\) 的异或和等于 \(k\),\(c\),\(d\) 的异或和。

转换完之后解法就出来了,我们先处理出 \(A\),\(B\) 拿出的数的异或值的所有可能,用一个键值对来表示每种异或值会出现几次。

然后枚举 \(C\),\(D\) 拿出的数和 \(K\) 的异或值的所有可能,对应的 \(a\bigoplus b\) 的出现次数全部加起来就是答案。时间复杂度 \(O(n^2)\)。

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
unordered_map<long long,long long> mp;
long long a[N],b[N],c[N],d[N];//因为数据较大,所以要开long long
int main(){
   std::ios::sync_with_stdio(0);
   cin.tie(0),cout.tie(0);
   int T;
   cin>>T;
   for(int id=1;id<=T;id++){
      mp.clear();
      int n;
      long long k;
      cin>>n>>k;
      for(int i=1;i<=n;i++){
         cin>>a[i];
      }
      for(int i=1;i<=n;i++){
         cin>>b[i];
      }
      for(int i=1;i<=n;i++){
         cin>>c[i];
      }
      for(int i=1;i<=n;i++){
         cin>>d[i];
      }
      for(int i=1;i<=n;i++){
         for(int j=1;j<=n;j++){
            mp[a[i]^b[j]]++;//统计出现次数
         }
      }
      long long ans=0;
      for(int i=1;i<=n;i++){
         for(int j=1;j<=n;j++){
            ans+=mp[k^c[i]^d[j]];//统计答案
         }
      }
      cout<<"Case #"<<id<<": "<<ans<<'\n';
   }
   return 0;
}
posted @ 2026-10-17 19:10  SCX2014  阅读(2)  评论(0)    收藏  举报