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

 

posted @ 2018-05-31 16:26  Drenight  阅读(186)  评论(0编辑  收藏  举报