1. 165E - Compatible Numbers Compatible Numbers
由于 , 那么显然找
的子集必然满足条件。不妨令
表示
的子集里存在于所给序列中的某一个,枚举子集即可。
/*
* @Author: Kurisu
*/
#include<bits/stdc++.h>
const int mod = 1e9 + 7;
const int N = (1 << 23) + 5;
int a[N], dp[N];
void solve() {
int n; std::cin >> n;
int bits = (1 << 23) - 1;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
dp[a[i]] = a[i];
}
for (int j = 0; j <= bits; j++) {
for (int i = 0; i <= 23; i++) {
if (dp[j]) { // 已经有了
continue;
}
if (j & (1 << i)) {
dp[j] |= dp[j ^ (1 << i)];
}
}
}
for (int i = 0; i <= n; i++) {
if (!dp[i]) {
dp[i] = -1;
}
}
for (int i = 1; i <= n; i++) {
if (dp[bits ^ a[i]]) { // 补集的子集存在于所给序列中
std::cout << dp[bits ^ a[i]] << ' ';
} else {
std::cout << -1 << ' ';
}
}
std::cout << '\n';
}
signed main() {
std::cin.sync_with_stdio(false), std::cin.tie(nullptr);
int T = 1; //std::cin >> T;
while (T--) {
solve();
}
return 0;
} 2. 1208F - Bits And Pieces
对 做
,只要有大于等于两个元素即可与
得到某一位的贡献,枚举
,从高位往低位,找到哪一位
不具有并且满足大于等于两个元素即可加上这一位。
/*
* @Author: Kurisu
*/
#include<bits/stdc++.h>
const int mod = 1e9 + 7;
const int N = (1 << 22) + 5;
int a[N], b[N];
void insert(int bits, int x) {
if (b[x] >= 2) {
return ;
}
if (bits == -1) {
b[x]++;
return ;
}
if (x & (1 << bits)) {
insert(bits - 1, x);
insert(bits - 1, x ^ (1 << bits));
} else {
insert(bits - 1, x);
}
}
int get(int bits, int x) {
int ans = 0, cur = 0;
for (int i = 21; i >= 0; i--) {
if (!(x & (1 << i))) { $这一位没有$
cur |= (1 << i);
if (b[cur] >= 2) { // 满足条件
ans |= (1 << i);
} else { // 无法做到,返回
cur ^= (1 << i);
}
}
}
return ans;
}
void solve() {
int n; std::cin >> n;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
}
int ans = 0;
for (int i = n; i >= 1; i--) {
if (i <= n - 2) {
ans = std::max(ans, a[i] | get(21, a[i]));
}
insert(21, a[i]);
}
std::cout << ans << '\n';
}
signed main() {
std::cin.sync_with_stdio(false), std::cin.tie(nullptr);
int T = 1; //std::cin >> T;
while (T--) {
solve();
}
return 0;
} 3. arc 100E
要求 ,显然
是
的一个子集,令
表示
的所有子集里
的最大值,一直取
就可以了。
/*
* @Author: Kurisu
*/
#include<bits/stdc++.h>
const int mod = 1e9 + 7;
const int N = (1 << 18) + 5;
std::pair<int, int> dp[N];
int a[N];
auto merge(std::pair<int, int> x, std::pair<int, int> y) {
std::pair<int, int> res = std::max(x, y);
if (res.second < std::min(x, y).first) {
res.second = std::min(x, y).first;
}
return res;
}
void solve() {
int n; std::cin >> n;
for (int i = 0; i < (1 << n); i++) {
std::cin >> a[i];
dp[i] = std::make_pair(a[i], -1e9);
}
for (int j = 0; j < n; j++) {
for (int i = 0; i < (1 << n); i++) {
if (i & (1 << j)) {
dp[i] = merge(dp[i], dp[i ^ (1 << j)]); // 子集
}
}
}
int ans = 0;
for (int i = 1; i < (1 << n); i++) {
ans = std::max(ans, dp[i].first + dp[i].second); // <= k,取 max
std::cout << ans << '\n';
}
}
signed main() {
std::cin.sync_with_stdio(false), std::cin.tie(nullptr);
int T = 1; //std::cin >> T;
while (T--) {
solve();
}
return 0;
} 4. 449D - Jzzhu and Numbers
令 为按位与和至少为
的状态数量,显然可以用
处理出来,这些状态要么取,要么不取,总共有
种可能,最后容斥一下得到结果为
的方案。
/*
* @Author: Kurisu
*/
#include<bits/stdc++.h>
const int mod = 1e9 + 7;
const int N = (1 << 22) + 5;
int a[N], dp[N];
long long qpow(long long a, long long b) {
long long res = 1;
while (b) {
if (b & 1) {
res = res * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return res;
}
int get1(int x) {
return (__builtin_popcount(x) & 1) ? -1 : 1;
}
void solve() {
int n; std::cin >> n;
for (int i = 1; i <= n; i++) {
std::cin >> a[i], dp[a[i]]++;
}
for (int i = 0; i <= 20; i++) {
for (int j = (1 << 20); j >= 0; j--) {
if (!(j & (1 << i))) { // 子集:1的位置可以是0,超集:0的位置可以是1
dp[j] = (dp[j] + dp[j | (1 << i)]) % mod; // 可以由超集转化而来
}
}
}
int ans = 0;
for (int i = 0; i < (1 << 20); i++) { // 容斥
ans = (ans + get1(i) * (qpow(2, dp[i]) - 1)) % mod;
ans = (ans + mod) % mod;
}
std::cout << ans << '\n';
}
signed main() {
std::cin.sync_with_stdio(false), std::cin.tie(nullptr);
int T = 1; //std::cin >> T;
while (T--) {
solve();
}
return 0;
} 
京公网安备 11010502036488号