这场被打爆了,写一下F的题解吧
- 大家好像都用的状压或者背包去做的,我贡献一个比较简单的做法。
表示当前i状态最少需要多少个数位与形成。
- 不难发现,重复的点对于答案的贡献为0,我们可以排序去重后线性dp一遍就行(这么做的话值域范围完全可以放到1000,这个题的值域范围比较小,也可以不去重排序直接做一遍就行)
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
using namespace std;
const int N = 2e5 + 10;
const int P = 1e9 + 7, INF = 0x3f3f3f3f;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef long long LL;
void solve() {
int n;
cin >> n;
vector<int> a(n);
vector<int> f(201, INF); //选择尽可能少的位与为0
for(int i = 0; i < n; i ++ )
cin >> a[i];
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end()) - a.begin();
for(int i = 0; i < a.size(); i ++ ) {
f[a[i]] = 1;
for(int j = 0; j <= 200; j ++ )
f[j & a[i]] = min(f[j & a[i]], f[j] + 1);
}
if(f[0] == INF) cout << "-1\n";
else cout << n - f[0] << '\n';
}
int main() {
//cout << log(200) / log(2) << '\n';
int T = 1;
cin >> T;
while(T -- ) {
solve();
}
return 0;
}