Description

Link.

给一个数列和 \(m\),在数列任选若干个数,使得他们的和对 \(m\) 取模后最大。

Solution

记录一下犯下的一个 nt 错误。

首先我们有一个显然的 DFS 暴力,每次两种决策,选或不选,所以时间复杂度为 \(\Theta(2^{n})\)。

\(n\) 的范围是 35,是过不了的,我们可以考虑折半搜索。

关于折半搜索可以看看 我的折半搜索小计

暴力搜出 \([1,\lfloor\frac{n}{2}\rfloor],[\lfloor\frac{n}{2}\rfloor+1,n]\) 的所有答案,记录到两个 vector 里面。

这一部分的时间复杂度是 \(\Theta(2^{\lfloor\frac{n}{2}\rfloor})\)。

考虑合并贡献。

先考虑一个暴力合并贡献的方法。

我们记第一次搜索搜出来的答案序列为 \(A_{1}\),同理有 \(A_{2}\)。

这里的两个答案序列都是在模 \(m\) 意义下的。

那么对于每一个 \(A_{1,i}\),我们都可以暴力在 \(A_{2}\) 中寻找两者相加模 \(m\) 的最大值。

那么我们可以分类讨论了,因为序列在模 \(m\) 意义下,所以我们对于每一个 \(A_{1,i}\) 找到的 \(A_{2,j}\) 使得 \((A_{1,i}+A_{2,j})\bmod m\) 最大,都只有两种情况。

一种是 \(A_{2,j}\) 在 \(A_{2}\) 中值域范围在 \([0,m-A_{1,i}-1]\) 的所有值中最大,一种是在 \(A_{2}\) 中值域范围在 \([0,m\times2-A_{1,i}-1]\) 的所有值中最大。

所以我们在这两种情况中取最大即可。

由于我不理解二分做法,所以我用的是动态开点值域线段树。

(flag:动态开点不加引用就【】)

#include<bits/stdc++.h>
using namespace std;
const int N=35+5;
const int H=99999999;
int n,m,tot=1,root=1,ans,a[N];
struct Tree
{
int ls,rs,val;
} nodes[(1<<(N>>1))<<3];
vector<int> vec[2]; void dfs(int x,int cur,int lim)
{
if(x>lim)
{
if(lim==(n>>1)) vec[0].push_back(cur);
else vec[1].push_back(cur);
return ;
}
dfs(x+1,(cur+a[x])%m,lim);
dfs(x+1,cur,lim);
} void ins(int &p,int l,int r,int x)
{
if(p==0) p=++tot;
if(l==r)
{
nodes[p].val=l;
return ;
}
int mid=(l+r)>>1;
if(mid>=x) ins(nodes[p].ls,l,mid,x);
else ins(nodes[p].rs,mid+1,r,x);
nodes[p].val=max(nodes[nodes[p].ls].val,nodes[nodes[p].rs].val);
} int find(int p,int l,int r,int x,int y)
{
if(l>y||r<x) return 0;
if(l>=x&&r<=y) return nodes[p].val;
int mid=(l+r)>>1,ret=0;
if(mid>=x) ret=max(ret,find(nodes[p].ls,l,mid,x,y));
if(mid<y) ret=max(ret,find(nodes[p].rs,mid+1,r,x,y));
return ret;
} void output(int p)
{
if(nodes[p].ls==0&&nodes[p].rs==0)
{
printf("%d ",nodes[p].val);
return ;
}
output(nodes[p].ls);
output(nodes[p].rs);
} signed main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
dfs(1,0,n>>1);
dfs((n>>1)+1,0,n);
sort(vec[0].begin(),vec[0].end());
sort(vec[1].begin(),vec[1].end());
for(auto x:vec[1]) ins(root,0,m-1,x);
for(auto x:vec[0]) ans=max(ans,max(x+find(1,0,m-1,0,m-x-1),(x+find(1,0,m-1,0,m*2-x-1))%m));
printf("%d\n",ans);
return 0;
}

Solution -「CF 888E」Maximum Subsequence的更多相关文章

  1. Solution -「CF 1342E」Placing Rooks

    \(\mathcal{Description}\)   Link.   在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...

  2. Solution -「CF 1622F」Quadratic Set

    \(\mathscr{Description}\)   Link.   求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...

  3. Solution -「CF 923F」Public Service

    \(\mathscr{Description}\)   Link.   给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...

  4. Solution -「CF 923E」Perpetual Subtraction

    \(\mathcal{Description}\)   Link.   有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...

  5. Solution -「CF 1586F」Defender of Childhood Dreams

    \(\mathcal{Description}\)   Link.   定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...

  6. Solution -「CF 1237E」Balanced Binary Search Trees

    \(\mathcal{Description}\)   Link.   定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...

  7. Solution -「CF 623E」Transforming Sequence

    题目 题意简述   link.   有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...

  8. Solution -「CF 1023F」Mobile Phone Network

    \(\mathcal{Description}\)   Link.   有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...

  9. Solution -「CF 599E」Sandy and Nuts

    \(\mathcal{Description}\)   Link.   指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...

  10. Solution -「CF 487E」Tourists

    \(\mathcal{Description}\)   Link.   维护一个 \(n\) 个点 \(m\) 条边的简单无向连通图,点有点权.\(q\) 次操作: 修改单点点权. 询问两点所有可能路 ...

随机推荐

  1. SpringBoot开发简单接口流程

    SpringBoot开发接口 初始化 新建项目 (1)使用 IDEA 的过程,新建Project,左侧选 Spring Initializr,点Next (2)选 8 版本,点Next (3)左侧选择 ...

  2. [ARM 汇编]进阶篇—存储访问指令—2.3.3 栈操作指令

    栈是一种特殊的数据结构,其特点是后进先出(LIFO,Last In First Out).在 ARM 汇编中,栈通常用于保存函数调用时的寄存器状态.局部变量和返回地址等.本节将详细介绍 ARM 汇编中 ...

  3. C++面试八股文:聊一聊指针?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第17面: 面试官:聊一聊指针? 二师兄:好的. 面试官:你觉得指针本质上是什么? 二师兄:这要从内存地址开始说起了.如果有一块容量是1G的内存,假设 ...

  4. 暴力密码破解工具——Hydra

    Hydra简介 hydra中文意思为九头蛇,它是黑客组织thc开发一款开源暴力密码破解工具,可以在线破解多种密码,支持Windows Linux MAC系统安装使用(Kali Linux自带), 支持 ...

  5. 每日一题 力扣 445 https://leetcode.cn/problems/add-two-numbers-ii/

    可以直接用栈去做就行,逆序想到栈的做法 然后算完一个就直接赋值给答案数组  我用的是常见 public ListNode addTwoNumbers(ListNode l1, ListNode l2) ...

  6. ENVI大气校正方法反演Landsat 7地表温度

    本文介绍基于ENVI软件,实现对Landsat 7遥感影像加以大气校正方法的地表温度反演操作. 目录 1 图像前期处理与本文理论部分 2 实际操作 2.1 植被覆盖度计算 2.2 地表比辐射率计算 2 ...

  7. Appium新版本引发的一个问题

    Appium新版本引发的一个问题 准备工作 测试代码 from appium import webdriver des_cap = {'platformName': 'android'} driver ...

  8. Easygraph:全面高效的图分析与社会计算开源工具

    前言图是对事物之间关系的一种原生的表达,利用图可以深入直接地认识世界中的关联.社交网络.交易数据.知识图谱.交通运输.生物技术等都是图数据的典型应用.社交网络是一种特殊的图数据,它建立在图网络的基础上 ...

  9. go build怎么使用

    go build 是 Go 语言编译器的一个命令,用于将 Go 源代码文件编译成可执行的二进制文件.它是 Go 语言开发过程中常用的一个命令.以下是 go build 的基本使用方法: go buil ...

  10. pyqt5中的布局方法

    addLayout():用于在布局中插入子布局 addWidget():用于在布局中插入控件