CF449D Jzzhu and Numbers
黄金定律:给定序列求答案,但答案与序列顺序无关的题目,要么考虑把序列转权值序列,要么对序列排序。
二进制题按大小排序看起来就没啥用,那就转成权值序列。即,设
然后直接算发现不是很好算。考虑容斥计算。
设
设 &
起来的值为
我们发现,这样的子序列中,里面每个数必须都是 &
起来之后 1
位势必会有丢失,无法是
换句话说,这个子序列必须从
然后考虑怎么选。发现只要保证每个数都是 &
起来之后 1
位肯定不会丢,一定是
所以选法是任意的,只要非空即可。在
所以,
答案要求的是 &
起来为
我们将满足这个条件的子序列称作满足第 &
起来的值的二进制第
我们发现,比如同时满足
那我们要统计的就是不满足任意属性的子序列数量。
根据容斥原理可以得到答案为
时间复杂度
/*
* @Author: crab-in-the-northeast
* @Date: 2023-04-18 19:02:58
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2023-04-18 19:23:43
*/
#include <bits/stdc++.h>
#define int long long
inline int read() {
int x = 0;
bool f = true;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
f = false;
for (; isdigit(ch); ch = getchar())
x = (x << 1) + (x << 3) + ch - '0';
return f ? x : (~(x - 1));
}
const int mod = (int)1e9 + 7;
const int lg = 20;
int g[(1 << lg) + 5], pw2[(1 << lg) + 5];
signed main() {
int n = read();
for (int i = 1; i <= n; ++i)
++g[read()];
pw2[0] = 1;
for (int i = 1; i < (1 << lg); ++i)
pw2[i] = pw2[i - 1] * 2 % mod;
for (int j = 0; j < lg; ++j) {
for (int i = (1 << lg) - 1; ~i; --i) {
if ((i & (1 << j)) == 0) {
int lst = i ^ (1 << j);
(g[i] += g[lst]) %= mod;
}
}
}
int ans = 0;
for (int x = 0; x < (1 << lg); ++x) {
(ans += (pw2[g[x]] - 1) * (__builtin_parityll(x) ? -1 : 1) + mod) %= mod;
}
printf("%lld\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】