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 }
来源是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]
------------------------------------------------------------------------------------------------------------------------
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 }