之前在cf上面接触过SOSdp(子集dp),这里就碰到了。
思路: 异或运算即非进位加法运算,因此如果需要进位的话,那么就无法满足题意,因此条件弱化为不需要进位,也就是不存在同一位上面都是1。也就是说,对于而言,中为1的地方,其他数不能为1,也就是说其对答案的贡献为的子集的个数。
#include <iostream>
using namespace std;
// SOS dp
int dp[(1 << 21)];
#define int long long
const int N = 21;
signed main()
{
int n;
cin >> n;
int a[n];
for(int i = 0 ; i <n ; i ++){
cin >> a[i];
dp[a[i]]++;
}
int ans = 0;
for(int i = 0;i < N; ++i) {
for(int mask = 0; mask < (1 << N); mask++){
if(mask & (1 << i))
dp[mask] += dp[mask^(1 << i)];
}
}
for(int i = 0 ; i < n ; i ++){
ans += dp[(1 << N) - 1 - a[i]];
}
cout << ans;
return 0;
}