E.Binary Cards(分治,贪心)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E.Binary Cards(分治,贪心)相关的知识,希望对你有一定的参考价值。
考虑 2 a 2^a 2a最多被选择一次.如果选择两次 2 a , 2 a 2^a,2^a 2a,2a,明显是不如选 2 a , 2 a + 1 2^a,2^a+1 2a,2a+1优秀
那么知道这个以后,就会发现如果选择 2 a 2^a 2a,就不会再选 2 − a 2^-a 2−a
因为 2 a , − 2 a 2^a,-2^a 2a,−2a肯定是不如 2 a , − 2 a + 1 2^a,-2^a+1 2a,−2a+1优秀的
这样我们就能得到对于一个 a a a,要么选择 2 a 2^a 2a,要么选择 2 − a 2^-a 2−a
我们从 a = 0 a=0 a=0的情况开始考虑
如果存在数是奇数,显然 2 0 2^0 20和 2 − 1 2^-1 2−1必选其一
如果都是偶数,那么没必要选,把所有数除以二进入一个相同的子问题
但是每次扫描判断是否有奇数,单次就是 O ( n ) O(n) O(n)的,而且还有那么多分治节点
但是注意到每次值域减小一半,意味着会有很多数字重复,那就排序去重可以降低复杂度
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
int n,a[maxn];
vector<int>nm;
vector<int> solve(int mx = 0)
if( mx>19 ) return vector<int>(0);
int ok = 0;
for( int &x:nm ) if( x&1 ) ok = 1; break;
if( !ok )//不用加数字这一位
for( int &x:nm ) x >>= 1;
return solve( mx+1 );
vector<int>temp = nm;
for( int&x:nm ) if( x & 1 ) x = ( x + 1 ) >> 1; else x >>= 1;
sort( nm.begin(),nm.end() );
nm.erase( unique( nm.begin(),nm.end() ),nm.end() );
vector<int>vec1 = solve( mx+1 );
nm = temp;
for(int&x:nm ) if( x & 1 ) x = ( x - 1 >> 1 ); else x >>= 1;
nm.erase( unique( nm.begin(),nm.end() ),nm.end() );
vector<int>vec2 = solve( mx+1 );
vec1.push_back( -(1<<mx) ); vec2.push_back( 1<<mx );
return vec1.size()<vec2.size()?vec1:vec2;
int main()
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i],nm.push_back( a[i] );
vector<int> ans = solve();
cout << ans.size() << endl;
for(int v:ans ) cout << v << " ";
以上是关于E.Binary Cards(分治,贪心)的主要内容,如果未能解决你的问题,请参考以下文章