合成小丹(dp+二进制按位或+结论)

problem

给定 nnn 个在 [0,2ω−1][0,2^\omega-1][0,2ω1] 内的整数。执行下面操作两种操作共 n−1n-1n1 次:

  1. 选择两个整数 x,yx,yx,y 从数列中删去,并加入 ⌊x∣y2⌋\lfloor\frac{x|y}{2}\rfloor2xy,这里的 | 表示按位或。
  2. 选择一个整数 xxx 从序列中删去。

不难发现每次操作后拥有的整数数量恰好少一,在 n−1n-1n1 次操作后你将得到恰好一个整数。

最小化这个整数并输出你的结果。

多组数据,1≤T≤101\le T\le 101T10

测试点编号nw特殊性质
$1 ∼ 2 $≤6≤ 66≤60≤ 6060
$3 ∼ 5 $≤8≤ 88≤60\le 6060
6∼86 ∼ 868≤300≤ 300300≤12≤ 1212
9∼129 ∼ 12912≤5000≤ 50005000≤18≤ 1818
13∼1513 ∼ 151315≤5000\le 50005000≤40≤ 4040
16∼1716 ∼ 171617≤105≤10^5105≤60≤ 6060A
18∼2018 ∼ 201820≤105\le 10^5105≤60\le 6060

特殊限制 A:保证所有 aia_iai 都可以表示成 222 的整数次幂减一的形式。

solution

⌊x∣y2⌋\lfloor\frac{x|y}{2}\rfloor2xy/2/2/2 可以看作二进制右移一位,⌊x∣y2⌋⇔(x∣y)>>1⇔(x>>1)∣(y>>1)⇔⌊x2⌋∣⌊y2⌋\lfloor\frac{x|y}{2}\rfloor\Leftrightarrow (x|y)>>1\Leftrightarrow (x>>1)\big|(y>>1)\Leftrightarrow \lfloor\frac{x}{2}\rfloor\big|\lfloor\frac{y}{2}\rfloor2xy(xy)>>1(x>>1)(y>>1)2x2y

可以看到按位或操作后再右移等价于各个元素分别右移后再按位或。

ci:aic_i:a_ici:ai 参与合并操作的次数 / 右移的位数。

ans=⌊a12c1⌋∣⌊a22c2⌋∣...∣⌊an2cn⌋ans=\lfloor\frac{a_1}{2^{c_1}}\rfloor\Big|\lfloor\frac{a_2}{2^{c_2}}\rfloor\Big|...\Big|\lfloor\frac{a_n}{2^{c_n}}\rfloorans=2c1a12c2a2...2cnan

有个显然是对的但又没想到的结论:在仅考虑合并操作的情况下,一组 {ci}\{c_i\}{ci} 合法当且仅当 ∑i=1n12ci=1\sum_{i=1}^{n}\frac{1}{2^{c_i}}=1i=1n2ci1=1

加上考虑删除操作的情况,可知一组 {ci}\{c_i\}{ci} 合法当且仅当 ∑i=1n12ci≥1\sum_{i=1}^n\frac{1}{2^{c_i}}\ge 1i=1n2ci11

因为如果满足和 ≥1\ge 11,那么一定存在子集 S⊂{1,2,...,n}S\subset\{1,2,...,n\}S{1,2,...,n} 满足 ∑i∈S12ci=1\sum_{i\in S}\frac{1}{2^{c_i}}=1iS2ci1=1,那么不在 SSS 内的就是被删除元素。

换言之,∑i=1n12ci\sum_{i=1}^n\frac{1}{2^{c_i}}i=1n2ci1 越大越有可能进入备选答案集合

  • case 6~8

基于此结论,我们可以设计一个非常暴力的状态转移方程。

fi,j:f_{i,j}:fi,j: 考虑 a[1∼i]a[1\sim i]a[1i] 这些数经过合并和删除一系列操作后的按位或为 jjj∑k=1i12ck\sum_{k=1}^i\frac{1}{2^{c_k}}k=1i2ck1 的最大值。

直接暴力转移,枚举 aia_iai 右移的位数 cic_ici
fi,j∣(ai>>ci)←max⁡fi−1,jf_{i,j|(a_i>>c_i)}\leftarrow^{\max}f_{i-1,j} fi,j(ai>>ci)maxfi1,j
状态数 O(n2ω)O(n2^\omega)O(n2ω),转移 O(ω)O(\omega)O(ω),时间复杂度 O(Tn2ωω)O(Tn2^\omega\omega)O(Tn2ωω)

for( int i = 0;i <= n;i ++ )for( int j = 0;j < (1 << w);j ++ )dp[i][j] = -1;
dp[0][0] = 0;
for( int i = 1;i <= n;i ++ ) for( int j = 0;j <= (1 << w);j ++ ) {dp[i][j] = max( dp[i][j], dp[i - 1][j] );if( dp[i - 1][j] != -1 )for( int k = 0;k <= w;k ++ )dp[i][j | (a[i] >> k)] = max( dp[i][j | (a[i] >> k)], dp[i - 1][j] + 1.0 / (1 << k) );}
for( int i = 0;i < (1 << w);i ++ )if( dp[n][i] >= 1 ) { printf( "%lld\n", i ); break; }
  • case 9~12

考虑对 dpdpdp 进行优化。

考虑答案的上下界。显然答案不会超过 2ω−⌊log⁡2n⌋2^{\omega-\lfloor\log_2n\rfloor}2ωlog2n(最大值与其余的数都进行合并操作)。

状态数 O(n2ω−⌊log⁡2n⌋)=O(2ω)O(n2^{\omega-\lfloor\log_2n\rfloor})=O(2^\omega)O(n2ωlog2n)=O(2ω),转移 O(ω−⌊log⁡2n⌋)O(\omega-\lfloor\log_2n\rfloor)O(ωlog2n),时间复杂度 O(Tω2ω)O(T\omega2^\omega)O(Tω2ω)

int m = 1 << (int)( w - log2( n ) + 1 );
for( int i = 0;i <= m;i ++ ) dp[0][i] = 0;
for( int i = 1;i <= n;i ++ ) {int d = i & 1;for( int j = 0;j <= m;j ++ ) dp[d][j] = dp[d ^ 1][j];for( int j = 0;j <= m;j ++ ) {for( int k = 0;k <= w;k ++ )if( ( j | (a[i] >> k) ) <= m )dp[d][j | (a[i] >> k)] = max( dp[d][j | (a[i] >> k)], dp[d ^ 1][j] + (1 << w - k) );}
}
for( int i = 0;i <= m;i ++ )if( dp[n & 1][i] >= (1 << w) ) { printf( "%lld\n", i ); break; }
  • case 13~15

通过最原始的暴力 dpdpdp 可知,我们能在 O(nω)O(n\omega)O(nω) 的时间内判断一个数 xxx 是否符合成为最后答案的要求。

O(n)O(n)O(n) 枚举 aia_iaiO(ω)O(\omega)O(ω) 枚举 cic_ici,在满足 (ai>>ci)∣x=x(a_i>>c_i)\big|x=x(ai>>ci)x=x 的前提下尽可能减小 cic_ici,等价于尽可能增大 12ci\frac{1}{2^{c_i}}2ci1

通过 ∑i=1n12ci≥1?\sum_{i=1}^n\frac{1}{2^{c_i}}\ge 1?i=1n2ci11? 来判断 xxx 能否成为候选答案。

所以我们贪心地从高位到低位考虑尽量填 000

具体而言,先初始 ans=2ω−1ans=2^\omega-1ans=2ω1(全 111),然后 i=ω→1i=\omega\rightarrow 1i=ω1 顺次考虑 ans−2ians-2^ians2i 是否可行,可行就 ans−=2ians-=2^ians=2i 即可。

时间复杂度 O(Tnω2)O(Tn\omega^2)O(Tnω2)

bool check( int ans ) {int sum = 0;for( int i = 1;i <= n;i ++ ) {for( int j = 0;j <= w;j ++ )if( ( ans | (a[i] >> j) ) == ans ) { sum += ( 1ll << w - j ); break; }if( sum >= (1ll << w) ) return 1;}return 0;
}
int ans = ( 1ll << w ) - 1;
for( int i = w - 1;~ i;i -- )if( check( ans ^ (1ll << i) ) ) ans ^= (1ll << i);
printf( "%lld\n", ans );
  • case 16~17,特殊情况 AAA

显然只需要尽可能让最高位 111 的二进制位最低。

那么每次从序列中选两个最大值,如果相同就合并右移一位,否则直接扔掉最大值。

priority_queue < int > q;
for( int i = 1;i <= n;i ++ ) q.push( a[i] );
while( q.size() > 1 ) {int x = q.top(); q.pop();int y = q.top(); q.pop();if( x == y ) q.push( x >> 1 );else q.push( y );
}
printf( "%lld\n", q.top() );
  • case 1~20

其实 case 13~15 已经非常接近正解了。

事实上,从高位到低位按位考虑的时候,每个 iiicic_ici 并不需要从头开始枚举。

因为为了满足前面更高位的一些限制的时候,有的 iii 就已经要求右移一定位数了。

那么此时我们完全可以直接从之前右移的位数继续累加考虑。

这样每个 iiicic_ici 就只变化了一个 1∼ω1\sim \omega1ω 的范围。

code

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 100005
int T, n, w;
int a[maxn], temp[maxn], g[maxn];signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld", &n, &w );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] );memset( g, 0, sizeof( g ) );int ans = (1ll << w) - 1;for( int k = w - 1;~ k;k -- ) {int now = ans ^ (1ll << k), sum = 0;for( int i = 1;i <= n;i ++ ) {temp[i] = g[i];while( ( a[i] >> g[i] | now ) ^ now ) g[i] ++;sum += 1ll << w - g[i];if( sum >= (1ll << w) ) sum = (1ll << w); //一直加可能炸long long}if( sum >= (1ll << w) ) ans = now;else memcpy( g, temp, sizeof( g ) );}printf( "%lld\n", ans );}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316559.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P2633 Count on a tree

P2633 Count on a tree 题意&#xff1a; 给定一棵 n 个节点的树&#xff0c;每个点有一个权值。有 m 个询问&#xff0c;每次给你 u,v,k&#xff0c;你需要回答 u xor last 和 v 这两个节点间第 k 小的点权。 其中last 是上一个询问的答案&#xff0c;定义其初始为 0&#…

[NewLife.XCode]增量累加

NewLife.XCode是一个有10多年历史的开源数据中间件&#xff0c;支持nfx/netstandard&#xff0c;由新生命团队(2002~2019)开发完成并维护至今&#xff0c;以下简称XCode。整个系列教程会大量结合示例代码和运行日志来进行深入分析&#xff0c;蕴含多年开发经验于其中&#xff0…

King of Range

King of Range 题意&#xff1a; 给你n个数&#xff0c;有m个询问&#xff0c;每次询问一个x&#xff0c;问有多少个区间的最大值减最小值大于x 题解&#xff1a; 我一开始的想法 st表实现区间最大减最小&#xff0c;利用二分来找这个区间范围&#xff0c;复杂度O(nmlogn)&…

膜拜大丹(结论+二元环)

problem 有两个国家&#xff0c;国家 AAA 有 nnn 座城市&#xff0c;国家 BBB 有 mmm 座城市&#xff0c;两个国家间有若干条单向航线。 具体地&#xff0c;有长度为 nnn 的数组 aaa 和长度为 mmm 的数组 bbb。国家 AAA 的第 iii 座城市有单向航线可以到达国家 BBB 的 1∼ai1…

Jewels

Jewels 题意&#xff1a; 你的坐标是(0,0,0)&#xff0c;有m个宝物&#xff0c;分别坐标是是(xi,yi,zi),它的z坐标以每秒下沉vi深度&#xff0c;你每次获取一个宝物的费用是两者的距离的平方&#xff0c;每秒只能获取一个宝物&#xff0c;从第0秒开始&#xff0c;问获取所有宝…

[NewLife.XCode]脏数据

NewLife.XCode是一个有10多年历史的开源数据中间件&#xff0c;支持nfx/netstandard&#xff0c;由新生命团队(2002~2019)开发完成并维护至今&#xff0c;以下简称XCode。整个系列教程会大量结合示例代码和运行日志来进行深入分析&#xff0c;蕴含多年开发经验于其中&#xff0…

[学习笔记] 二分图基础定理的相关证明

最小点集覆盖最大匹配 最小点集覆盖&#xff1a;选出最少的点使得每条边都至少有一个端点被选。 先证最小点集覆盖 ≥\ge≥ 最大匹配 假设最大匹配为 xxx&#xff0c;即有 xxx 条边两两之间没有公用点。 光覆盖这些边就要用到 xxx 个点。 “不少于”已证。 再证最小点集覆盖 …

Boxes

Boxes 题意&#xff1a; 有n个盒子&#xff0c;每个盒子里要么是黑球&#xff0c;要么是白球&#xff0c;你可以花C的代码得知剩下所有盒子中黑球数量和白球数量&#xff0c;(只是知道总数量&#xff0c;并不知道具体哪个盒子里是什么)&#xff0c;你可以可以花费wi的代价开第…

Double Strings

Double Strings 题意&#xff1a; 给你s和t两个字符串&#xff0c;在其中选出两个等长的子序列(可以不连续)a&#xff0c;b&#xff0c;满足a的字典序严格小于b的字典序&#xff0c;问方案数,答案mod(1e97) 题解&#xff1a; 好的方案的构成是一段相同的前缀一个不同的字符…

你真的了解用户吗?-浅谈《用户画像》的意义和方法

作者&#xff1a;陈炯关于作者系统集成项目管理高级工程师某大型国有银行高级质量管理师从事IT项目管理工作十余年具有丰富的开发与管理经验公司内部敏捷转型的发起者之一深度参与敏捷实践与总结大学校园里流传最广的一句话是什么&#xff1f;“防火防狼防师兄”。为什么师兄这…

[学习笔记] 二次剩余

二次剩余 对于素数 ppp 和数 aaa&#xff0c;满足 (a,p)1(a,p)1(a,p)1。&#xff08;注意 aaa 不一定小于 ppp&#xff09; 若 ∃xx2≡a(modp)\exist_{x}\ x^2\equiv a\pmod p∃x​ x2≡a(modp)&#xff0c;则称 aaa 是模 ppp 意义下的二次剩余&#xff0c;xxx 称为该二次剩余…

Script Lab 续:为 Officejs 开发配置 VSCode 环境

垫场AA&#xff1a;深度&#xff1a;从 Office 365 新图标来看微软背后的设计新理念--------------------------------------------------前期01&#xff1a;尝试&#xff1a;Script Lab&#xff0c;快速 Office 365 开发工具前期02&#xff1a;尝试&#xff1a;Script Lab&…

P3567 [POI2014]KUR-Couriers

P3567 [POI2014]KUR-Couriers 题意&#xff1a; 给一个长度为 n 的正整数序列 a。共有 m 组询问&#xff0c;每次询问一个区间 [l,r] &#xff0c;是否存在一个数在 [l,r]中出现的次数严格大于一半。如果存在&#xff0c;输出这个数&#xff0c;否则输出 0。 题解&#xff1…

[WC 2022 Day3 zmy] Od deski do deski(dp)

设 fi:1∼if_{i}:1\sim ifi​:1∼i 能否分成若干个首尾相同的区间 则有 fiORj<i(fj−1∧ajai)f_{i}\text{OR}_{j<i}(f_{j-1}\wedge a_ja_i)fi​ORj<i​(fj−1​∧aj​ai​)。 这是最原始的暴力 dpdpdp&#xff0c;时间 O(n2m)O(n^2m)O(n2m)。 事实上&#xff0c;这…

编程方式重启 ASP.NET Core 网站

点击上方蓝字关注“汪宇杰博客”常言道&#xff0c;多喝热水&#xff0c;重启试试。有时候当应用工作不正常&#xff0c;重启也许能解决问题。但是程序员通常接触不到服务器系统权限。而运维人员和公司流程经常人为制造麻烦阻止我们去重启应用。老实的程序员不善言辞交际&#…

可持久化3--可持久化01Trie

01Trie 可持久化 01Trie 的方式和可持久化值域线段树的方式是相似的&#xff0c;只是以 01字典树 的方式来维护值域。一般用来解决异或相关的能够按位贪心的题目。 其实就是将可持久化线段树中的操作嫁接到01Trie中&#xff0c;这样就是解决任意一个区间内的问题。 例题&…

AGC044E Pandom Pawn(期望+凸包)

最开始我们先旋转一下这张桌子&#xff0c;使得 A1An1max⁡{Ai}A_1A_{n1}\max\{A_i\}A1​An1​max{Ai​}。 这是非常有效的&#xff0c;因为我们把环就变成链&#xff0c;只要到达了链的任意一端 1/n11/n11/n1 就肯定会结束游戏。 定义 Ei:E_i:Ei​: 从 iii 开始游戏&#xf…

.NET Core 容器化调查

前几天在微信朋友圈做了一个简单的调查&#xff0c;参与人数有500人&#xff0c;调查结果如下&#xff1a;使用K8S的比例非常类似于2017年初我在公众号里针对.NET Core的使用情况的比例。.NET Core是针对云原生应用开发而重新设计的一个平台&#xff0c;.NET Core借鉴了.NET Fr…

P4735 最大异或和

P4735 最大异或和 题意&#xff1a; 一个非负序列a&#xff0c;初始长度为n&#xff0c;有两种操作&#xff1a; A x&#xff0c;在序列中添加x&#xff0c;n加一Q l r x,询问操作&#xff0c;询问一个位置p&#xff0c;p满足l<p<r,使得p到位置n的的异或和与x的异或值…

[学习笔记] 单位根反演

单位根反演 [k∣n]1k∑i0k−1ωkin[k\mid n]\frac 1k\sum_{i0}^{k-1}\omega_k^{in}[k∣n]k1​∑i0k−1​ωkin​ kkk 次单位根是 kkk 次幂为 111 的复数解 wkw_kwk​。利用单位圆和单位根的关系很容易证明。 k∣nk\mid nk∣n 显然 ωkin\omega_k^{in}ωkin​&#xff0c;相当于…