sosdp 二进制子集的贡献
可以O(n*2^n)算出n位每个mask值所包含子集的二进制码下标的贡献
比如f[5]=a[0]+a[1]+a[4]+a[5]这种的,101包含了000,001,100,101
1 #include<bits/stdc++.h> 2 //#pragma comment(linker, "/STACK:1024000000,1024000000") 3 #include<stdio.h> 4 #include<algorithm> 5 #include<queue> 6 #include<string.h> 7 #include<iostream> 8 #include<math.h> 9 #include<stack> 10 #include<set> 11 #include<map> 12 #include<vector> 13 #include<iomanip> 14 #include<bitset> 15 #include<stdint.h> 16 17 using namespace std; // 18 19 #define ll long long 20 #define ull unsigned long long 21 #define pb push_back 22 #define FOR(a) for(int i=1;i<=a;i++) 23 #define sqr(a) (a)*(a) 24 #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)) 25 ll qp(ll a,ll b,ll mod){ 26 ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t; 27 } 28 struct DOT{int x;int y;}; 29 inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} 30 void ex(){puts("NO");exit(0);} 31 const int dx[8]={0,0,-1,1,-1,1,-1,1}; 32 const int dy[8]={1,-1,0,0,-1,1,1,-1}; 33 const int inf=0x3f3f3f3f; 34 const ll Linf=0x3f3f3f3f3f3f3f3fLL; 35 const ll Mod=1e18+7; 36 const double eps=1e-6; 37 const double pi=acos(-1.0); 38 39 const int maxn=1e6+33; 40 41 int n; 42 int a[maxn],f[maxn]; 43 44 int main(){ 45 scanf("%d",&n); 46 for(int i=0;i<(1<<n);i++){ 47 scanf("%d",&a[i]); 48 } 49 for(int i=0;i<(1<<n);i++){ 50 f[i]=a[i]; 51 } 52 for(int i=0;i<n;i++){ 53 for(int msk=0;msk<(1<<n);msk++){ 54 if(msk & (1<<i)) 55 f[msk]+=f[msk^(1<<i)]; 56 } 57 } 58 }
View Code
来源是cf上的一篇博客
核心思想就是从低位枚举到高位,
f[mask][i]表示mask码低i位子集的贡献
如果mask的第i位是1,那么f[mask][i]=f[mask][i-1]+f[mask^(1<<i)][i-1],很巧妙地以第i位的01作为子集划分
如果mask的第i位是0,那么f[mask][i]=f[mask][i-1]
------------------------------------------------------------------------------------------------------------------------
例题SPECIAL PAIRS
1e5的数列问有多少个pair满足a[i]&a[j]=0
对于a[i],与他匹配的a[j]一定都贡献进a[i]的补集,那么答案就是sigma(f[补ai])
1 #include<bits/stdc++.h> 2 //#pragma comment(linker, "/STACK:1024000000,1024000000") 3 #include<stdio.h> 4 #include<algorithm> 5 #include<queue> 6 #include<string.h> 7 #include<iostream> 8 #include<math.h> 9 #include<stack> 10 #include<set> 11 #include<map> 12 #include<vector> 13 #include<iomanip> 14 #include<bitset> 15 #include<stdint.h> 16 17 using namespace std; // 18 19 #define ll long long 20 #define ull unsigned long long 21 #define pb push_back 22 #define FOR(a) for(int i=1;i<=a;i++) 23 #define sqr(a) (a)*(a) 24 #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)) 25 ll qp(ll a,ll b,ll mod){ 26 ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t; 27 } 28 struct DOT{int x;int y;}; 29 inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} 30 void ex(){puts("NO");exit(0);} 31 const int dx[8]={0,0,-1,1,-1,1,-1,1}; 32 const int dy[8]={1,-1,0,0,-1,1,1,-1}; 33 const int inf=0x3f3f3f3f; 34 const ll Linf=0x3f3f3f3f3f3f3f3fLL; 35 const ll Mod=1e18+7; 36 const double eps=1e-6; 37 const double pi=acos(-1.0); 38 39 const int maxn=1e6+3; 40 41 int n;int b[100011]; 42 int a[maxn],f[maxn]; 43 int T; 44 int main(){ 45 read(T); 46 while(T--){ 47 memset(a,0,sizeof a); 48 read(n); 49 for(int i=0;i<n;i++){ 50 read(b[i]); 51 a[b[i]]++; 52 } 53 54 for(int i=0;i<maxn;i++){ 55 f[i]=a[i]; 56 } 57 int lim=log2(maxn); 58 for(int i=0;i<lim;i++){ 59 for(int msk=0;msk<maxn;msk++){ 60 if(msk & (1<<i)) 61 f[msk]+=f[msk^(1<<i)]; 62 } 63 } 64 ll ans=0; 65 66 for(int i=0;i<n;i++){ 67 ans+=f[((1<<lim)-1) ^ b[i]]; 68 } 69 printf("%lld\n",ans); 70 } 71 }
View Code
转载于:https://www.cnblogs.com/Drenight/p/9117399.html
sosdp 二进制子集的贡献相关推荐
- 二进制子集生成与排列组合
二进制子集生成与排列组合 咳咳,二进制我觉得很有必要单独列出来,二进制的玩法还是很多的,比较多的就是表示多重状态,因为只有1和0的存在,每一位可以表示可取或者不可取,还能配合排列组合使用,来试试. 首 ...
- LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)
文章目录 1. 题目 2. 解题 1. 题目 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件, ...
- hdu5823 (附带数的二进制子集)
二进制数子集的取法,结果不会输出0,且从大到小 for(int i0 = i;i0;i0=(i0-1)&i)cout<<i0<<endl; 题意: 给定一个 N个点的图 ...
- 移位运算符解子集问题--用移位运算符转十进制为二进制
想直接看十进制转二进制的同学可以跳转: 目录 p.用移位运算符转十进制为二进制 子集是一个数学概念:如果集合A的任意一个元素都是集合B的元素,那么集合A称为集合B的子集. --百度百科 现在给你一个数 ...
- 2020 区域赛(沈阳) M. United in Stormwind fwt + sosdp
传送门 文章目录 题意: 思路: 题意: 有nnn个试卷,每个试卷有mmm个问题,每个问题有两个选项a,ba,ba,b,定义两个试卷不同当且仅当其选中的问题中有一个问题不同.现在问你对于mmm个问题的 ...
- LeetCode 2002. 两个回文子序列长度的最大乘积(状态压缩+枚举状态子集+预处理)
文章目录 1. 题目 2. 解题 2.1 超时 2.2 预处理优化 1. 题目 给你一个字符串 s ,请你找到 s 中两个 不相交回文子序列 ,使得它们长度的 乘积最大 . 两个子序列在原字符串中如果 ...
- (二进制枚举+思维)1625 夹克爷发红包
1625 夹克爷发红包 1 秒 131,072 KB 20 分 3 级题 在公司年会上,做为互联网巨头51nod掌门人的夹克老爷当然不会放过任何发红包的机会. 现场有n排m列观众,夹克老爷会为每一名观 ...
- 三进制计算机_漫话二进制
时间兜兜转转,终于又来到了乐博小课堂的时间,在讲今天要讲的内容之前,乐博客先给大家讲一个笑话: "世界上只有10种人,一种懂二进制,另一种不懂二进制." 这个笑话展示的就是我们这次 ...
- 2017 Multi-University Training Contest 1 solutions BY 北京航空航天大学
转自 http://bestcoder.hdu.edu.cn/blog/ 1001. Add More Zero 答案就是 ⌊log10(2m−1)⌋\left \lfloor \log_{10}(2 ...
最新文章
- mysql怎么引用别的文件_用source语句引用mysql文件的细节注意
- 自定义实现ProgressDialog样式的Dialog
- github上传本地项目_提交本地项目到GitHub
- 动态规划训练17 [Super Jumping! Jumping! Jumping! HDU - 1087 ]
- python自动化测试脚本可以测php吗_python unittest实现api自动化测试_python
- JavaScript中的const
- 我不够格,但我还是希望事情到此为止,继续工作罢
- MyEclipse6.5注册码(转)
- 对接码是什么意思_设备对接是什么意思
- 用 MeGUI 压制 DVDrip 入门
- 微信小程序实现城市搜索功能(付源码)
- 阿里20亿美金收购考拉,丁磊到底是怎么“失身”的?
- git合并某个分支的某次提交(cherry-pick)
- LTE - RA preamble的选择与其发送所需prach资源的选择
- QQ IDKey生成
- 网络工程师成长日记424-造假的人
- 全国计算机竞赛能保送清华北大吗,NOIP考试是什么?能保送清华北大是真的吗?...
- 各位集美兄得看过来! 利用AI给青春有你2的选手们做数据分析挖掘(三):看图像识选手
- 有关Linux 软件包管理器 yum的命令打字练习
- 外网映射nginx端口丢失问题解决