当前位置: 首页 > news >正文

sosdp

子集 dp

sosdp,高维前缀和。

传统的,计算二维前缀和的递推式为:
si,j←si−1,j+si,j−1−si−1,j−1s_{i,j}\leftarrow s_{i-1,j}+s_{i,j-1}-s_{i-1,j-1}si,jsi1,j+si,j1si1,j1

这可以等价于,每一维上,这个点加上该维上一个点的和。我们不妨把它拓展到 nnn 维,用二进制位表示高维。

1.高维前缀和

给定一个含 2n2^n2n 个整数的集合 AAA,我们需要计算:∀T⊆A\forall T\subseteq ATATTT 中所有元素 AiA_iAi 之和,iii 为元素对应下标,写为:
Fmask=∑i∈maskAiF_{mask}=\sum_{i\in mask}A_iFmask=imaskAi

for(int i=0;i<(1<<N);i++)
f[i]=A[i];
for(int i=0;i<N;i++)
for(int mask=0;mask<(1<<N);mask++)
if(mask&(1<<i))f[mask]+=f[mask^(1<<i)];

光这么看肯定很难看出算法的精髓所在。应当搭配例题食用。

我的题单。

2.AT_arc100_c Or Plus Max

题意

有一个长度为 2N2^N2N 的整数序列 A0,A1,...,A2N−1A_0,\ A_1,\ ...,\ A_{2^N-1}A0, A1, ..., A2N1。(注意下标从 000 开始)

对于所有满足 1≤K≤2N−11\leq K\leq 2^N-11K2N1 的整数 KKK,请解决以下问题:

  • i,ji,ji,j 为整数,满足 0≤i<j≤2N−10\leq i<j\leq 2^N-10i<j2N1,且 (ior j)≤K(i\ \text{or}\ j)\leq K(i or j)K,求 Ai+AjA_i+A_jAi+Aj 的最大值。这里 ororor 表示按位或运算。

1≤N≤181\leq N\leq 181N181≤Ai≤1091\leq A_i\leq 10^91Ai109

思路

首先 i≠ji\neq ji=j,我们发现 mask=ior jmask=i\ \text{or}\ jmask=i or j 的含义是,i,ji,ji,j 分别是 maskmaskmask 的两个不同子集。

那么可以贪心地,对于每个 maskmaskmask,求出其子集下标中的最大值 fmaskf_{mask}fmask 以及次大值 gmaskg_{mask}gmask。求法就是上面的求和改成维护最大值和次大值。

那么答案就是:
max⁡mask≤Kfmask+gmask\max_{mask\le K}f_{mask}+g_{mask}maskKmaxfmask+gmask

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const ll N=23,S=1<<N;
ll n;
ll a[S];
ll f[S],g[S];//集合i子集最大和和次大和 
int main()
{scanf("%lld",&n);for(int i=0;i<(1<<n);i++){scanf("%lld",&a[i]);f[i]=a[i];}for(int i=0;i<n;i++){for(int mask=0;mask<(1<<n);mask++){if(mask&(1<<i)){if(f[mask^(1<<i)]>f[mask]){g[mask]=f[mask];f[mask]=f[mask^(1<<i)];}else if(f[mask^(1<<i)]>g[mask])g[mask]=f[mask^((1<<i))];}}}ll ans=0;for(int i=1;i<(1<<n);i++)//ansk=max(1~k){ans=max(ans,f[i]+g[i]);printf("%lld\n",ans);}return 0;
}

3.CF165E Compatible Numbers

题意

如果两个整数 xxxyyy 的按位与运算结果为 000,即 x&y=0x\ \&\ y=0x & y=0,那么它们是兼容的。例如,90(10110102)90\ (1011010_2)90 (10110102)36(1001002)36\ (100100_2)36 (1001002) 是兼容的,因为 10110102&1001002=021011010_2\ \&\ 100100_2=0_210110102 & 1001002=02,而 3(112)3\ (11_2)3 (112)6(1102)6\ (110_2)6 (1102) 则不兼容,因为 112&1102=10211_2\ \&\ 110_2=10_2112 & 1102=102

给定一个整数数组 a1,a2,…,ana_1,a_2,\ldots,a_na1,a2,,an。你需要判断,对于每个数组元素,是否存在数组中的其它元素跟它兼容?如果存在兼容元素,还需要输出一个满足条件的元素。

1≤n≤1061\le n\le 10^61n1061≤ai≤4×1061\le a_i\le 4\times 10^61ai4×106

思路

对于一个数 aia_iai,对其二进制逐位取反得到 flapiflap_iflapi,即找 flapiflap_iflapi 子集中对应下标的最大值。维护 fmaskf_{mask}fmask 表示 maskmaskmask 子集内的下标最大值即可,答案就是 fflapif_{flap_i}fflapi

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const ll N=1e6+9,M=22,S=5e6+9,inf=0x3f3f3f3f;
ll n;
ll a[N];
ll f[S];
ll flap(ll x)
{return (~x)&((1<<M)-1);
}
int main()
{scanf("%lld",&n);memset(f,-1,sizeof(f));for(int i=0;i<n;i++){scanf("%lld",&a[i]);f[a[i]]=i;}for(int i=0;i<M;i++){for(int mask=0;mask<(1<<M);mask++){if(mask&(1<<i))f[mask]=max(f[mask],f[mask^(1<<i)]);}}for(int i=0;i<n;i++){ll ret=f[flap(a[i])];if(ret==-1)printf("-1 ");else printf("%lld ",a[ret]);}return 0;
}
http://www.dtcms.com/a/445686.html

相关文章:

  • 快速了解BERT
  • 在线Deflate压缩工具(支持添加zlib头及无zlib头模式)
  • 第14节-增强表结构-ALTER-TABLE
  • Ubuntu之apt更新源
  • T527 IR-RX 调试
  • 低成本能谱仪设计:基于分立器件的模拟前端与数字后端实现方案
  • 计算机视觉的数据收集与标注
  • LeetCode:92.最小路径和
  • 百度竞价推广属于什么广告广东网站se0优化公司
  • Anaconda路径配置
  • GitHub 热榜项目 - 日榜(2025-10-05)
  • java中Math.random()和random()方法区别
  • Django SimpleUI 详解:现代化的Django Admin界面美化方案
  • 网站开发客户流程 6个阶段简述常用的网站开发软件
  • 区块链分层学:新的开始
  • Qt与CMakeLists.txt
  • Ubuntu20.04安装Anaconda3-2025.06
  • VirtualBox中ubuntu1804虚拟机共享文件夹设置
  • 基于单片机的环境监测智能报警系统的设计(论文+源码)
  • 成都网页制作推广合肥网站seo报价
  • 短波红外相机在工业视觉检测中的应用
  • 马鞍山市建设银行网站科右前旗建设局网站
  • 【傻呱呱】托管项目到GitHub(纯前端UI操作)
  • 神经网络之激活函数Softmax
  • 高端网站建设哪家公司好网站建设招标样本
  • Qt Quick 3D-机械臂模型显示与交互
  • 轻松Linux-10.进程信号
  • 淘宝网站可信度状况及建设策略桂林网站
  • HTML简单入门—— 基础标签与路径解析
  • AI Agent:从“超级玩具“到“核心生产力“,智能新纪元的深度解析