CF449D Jzzhu and Numbers
给出一个长度为n的序列a1,a2...ana1,a2...an。求构造出一个序列i1≤i2≤...≤ik(1≤k≤n)i1≤i2≤...≤ik(1≤k≤n)使得ai1&ai2&...&aik=0ai1&ai2&...&aik=0 。求方案数模109+7109+7 。
也就是从{ai}{ai} 里面选出一个非空子集使这些数按位与起来为0.
n≤106,ai≤106n≤106,ai≤106
发现这个就是个与意义下的背包,然后考虑用 FWT 优化,我们每次加入一个物品之后会有两种选择,也就是会使其 ×2×2 ,那么用桶记录下 ii 有多少个,然后 FWT 过去,这里的 AiAi 就是每个位置上的翻倍的倍数了,算出来之后再 IFWT 回去就可以了。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
const int N = 20;
const int p = 1e9 + 7;
using namespace std;
int n,a[1 << N],t[1 << N],m2[1 << N];
void FWT(int *a)
{
for (int i = 1;i < (1 << N);i <<= 1)
for (int j = 0;j < (1 << N);j += i << 1)
for (int k = 0;k < i;k++)
{
int a0 = a[j + k],a1 = a[j + k + i];
a[j + k] = a1;
a[j + k + i] = (a0 + a1) % p;
}
}
void IFWT(int *a)
{
for (int i = 1;i < (1 << N);i <<= 1)
for (int j = 0;j < (1 << N);j += i << 1)
for (int k = 0;k < i;k++)
{
int a0 = a[j + k],a1 = a[j + k + i];
a[j + k] = (-a0 + a1) % p;
a[j + k + i] = a0;
}
}
int main()
{
scanf("%d",&n);
m2[0] = 1;
for (int i = 1;i < (1 << N);i++)
m2[i] = 2ll * m2[i - 1] % p;
for (int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
t[a[i]]++;
}
FWT(t);
for (int i = 0;i < (1 << N);i++)
t[i] = m2[t[i]];
IFWT(t);
cout<<(t[0] + p) % p<<endl;
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
· C# 13 中的新增功能实操
· Supergateway:MCP服务器的远程调试与集成工具
· Vue3封装支持Base64导出的电子签名组件