ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SOSdp

2021-04-04 10:33:00  阅读:245  来源: 互联网

标签:int mask long SOSdp ans dp define


SOSdp

https://codeforces.ml/contest/383/problem/E

https://codeforces.ml/blog/entry/45223

E. Compatible Numbers

题意

给定 a i a_i ai​,对每个数找到一个 a j a_j aj​满足 a i & a j = 0 a_i\& a_j=0 ai​&aj​=0

思路

S O S d p SOS dp SOSdp

在原定义: f [ m a s k ] = ∑ i & m a s k = i a i f[mask]=\sum\limits_{i\&mask=i}a_i f[mask]=i&mask=i∑​ai​

将其修改为 f [ m a s k ] = f[mask]= f[mask]=属于 m a s k mask mask子集的其中一个数 a i a_i ai​。

也就是把求和该为只保存一个数。

这样我们要求 a n s [ a i ] ans[a_i] ans[ai​]就等价于求 f [ a l l ⊕ a i ] f[all\oplus a_i] f[all⊕ai​], a l l = ( 2 20 − 1 ) all=(2^{20}-1) all=(220−1),所有位为 1 1 1。

时间复杂度: O ( N × 2 N ) O(N\times 2^N) O(N×2N)

注意初始化不存在情况为 − 1 -1 −1。

code

// Problem: E. Compatible Numbers
// Contest: Codeforces - Codeforces Round #112 (Div. 2)
// URL: https://codeforces.ml/contest/165/problem/E
// Memory Limit: 256 MB
// Time Limit: 4000 ms
// Date: 2021-03-13 15:01:57
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e6+5,M=1<<22,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
int f[M],n,a[N];
int main(){
	scanf("%d",&n);mst(f,-1);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]),f[a[i]]=a[i];
	}
	//printf("%d %d\n",f[a[1]],f[a[2]]);
	int st=1<<22;
	for(int i=0;i<22;i++)
		for(int j=0;j<st;j++){
			if((j>>i&1)&&(~f[j^(1<<i)])) f[j]=f[j^(1<<i)];
		}
	for(int i=1;i<=n;i++)
		printf("%d ",f[(st-1)^a[i]]);
	return 0;
}

D. Jzzhu and Numbers

题意

给定 a i a_i ai​,求满足子集按位与之和为 0 0 0的子集数。

思路

容斥原理+SOSdp

考虑令 a n s = ∣ W 1 ‾ ∩ W 2 ‾ ∩ W 3 ‾ ⋯ ∩ W k ‾ ∣ ans=|\overline{W_1}\cap\overline{W_2}\cap\overline{W_3}\dots\cap\overline{W_k}| ans=∣W1​​∩W2​​∩W3​​⋯∩Wk​​∣

W i W_i Wi​表示二进制第 i i i位为1的方案数。(从第一位开始计算)

根据容斥原理: a n s = t o t − ∣ W 1 ‾ ∪ W 2 ‾ ∪ W 3 ‾ ⋯ ∪ W k ‾ ∣ ans=tot-|\overline{W_1}\cup\overline{W_2}\cup\overline{W_3}\dots\cup\overline{W_k}| ans=tot−∣W1​​∪W2​​∪W3​​⋯∪Wk​​∣

当为1的个数为奇数就是减,否则为加。

因为枚举位不好枚举,所以我们考虑枚举子集对应的情况。

即: f [ m a s k ] = ∑ m a s k & a i = a i ∣ S ∣ f[mask]=\sum\limits_{mask\&a_i=a_i}|S| f[mask]=mask&ai​=ai​∑​∣S∣,即满足条件的 a i a_i ai​个数。

这样答案就是 2 ∣ S ∣ − 1 2^{|S|}-1 2∣S∣−1个,因为不能一个不取,否则与运算为 0 0 0。

递推也与 S O S d p SOSdp SOSdp类似,具体看代码。

code

// Problem: D. Jzzhu and Numbers
// Contest: Codeforces - Codeforces Round #257 (Div. 1)
// URL: https://codeforces.ml/problemset/problem/449/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Date: 2021-03-13 15:49:29
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=20,M=1<<20,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
int dp[M],n;
ll p[M],msk[M];
void init(int n){
	p[0]=1;
	for(int i=1;i<=n;i++) p[i]=p[i-1]*2%mod,msk[i]=msk[i&(i-1)]+1;
}
int main(){
	scanf("%d",&n);
	init(M-1);
	for(int i=1,x;i<=n;i++){
		scanf("%d",&x);dp[x]++;
	}
	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++) if(j>>i&1) dp[j^(1<<i)]+=dp[j];
	ll ans=0;
	for(int i=0;i<M;i++){
		int f=(msk[i]&1)?-1:1;
		ans=(ans+1LL*f*(p[dp[i]]-1))%mod;
	}
	printf("%lld\n",(ans%mod+mod)%mod);
	return 0;
}

CCA的区间

题意

给定 n n n个 2 2 2的幂次数,至多翻转一次区间,求最大子区间和。

思路

至多翻转一次区间等价于求两个不相交区间的最大和,考虑 S O S d p SOSdp SOSdp,令 d p [ m a s k ] dp[mask] dp[mask]为属于 m a s k mask mask子集的最大答案。

然后对当前状态 i i i取反,即 a n s = m a x ( a n s , d p [ i ] + d p [ a l l ⊕ i ] ) ans=max(ans,dp[i]+dp[all\oplus i]) ans=max(ans,dp[i]+dp[all⊕i])即可。

时间复杂度: O ( N × 2 N ) O(N\times 2^N) O(N×2N)

code

// Problem: CCA的区间
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11168/E
// Memory Limit: 524288 MB
// Time Limit: 4000 ms
// Date: 2021-03-13 16:39:09
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e5+5,M=1<<24,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
int a[N],n,dp[M];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		int x=0;
		for(int j=i;j;j--){
			if(x&a[j]) break;
			x|=a[j];
			dp[x]=x;
		}
	}
	for(int i=0;i<24;i++)
		for(int j=0;j<M;j++) if(j>>i&1) dp[j]=max(dp[j],dp[j^(1<<i)]);
	int ans=0;
	for(int i=0;i<M;i++) ans=max(ans,dp[i]+dp[(M-1)^i]);
	printf("%d\n",ans);
	return 0;
}

标签:int,mask,long,SOSdp,ans,dp,define
来源: https://blog.csdn.net/weixin_45750972/article/details/115425904

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有