• Codeforces 949E Binary Cards


    Description

    给出一个长度为 (n) 的数组,求使得用最少数量的 (2^k)(-2^k) 的数,使得数组中的每一个元素都可以被你选出的 (2) 的次幂表示
    题面

    Solution

    注意到两个性质:
    1.一个数不会用两次,举个例子:用两个 (2),不如用 (2,4) 范围广
    2.一个数不会既用 (2^k) 又用 (-2^k),显然用 (-2^k,2^{k+1}) 或者 (2^k,-2^{k+1}) 更优

    这样就可以依次考虑每一位了:
    如果所有的数都不含有这一位,那么就直接把所有的数除以 (2)
    如果存在数含有这一位,那么用 (-2^k) 或者 (2^k) 把含有这一位的数都给去掉,然后再把所有的数除以 (2)
    对于第二种情况我们直接搜索一下就好了

    这样复杂度有些问题,但是我们把数去重之后,第 (k) 层的数就最多只有 (frac{max(A[i])}{2^{k}})
    复杂度就变成了分治的复杂度了

    #include <bits/stdc++.h>
    using namespace std;
    const int N=100010;
    int a[N],b[21][N],top=0,st[N],ans[N],anslen=N;
    inline void dfs(int t,int n){
    	if(t>20 || top>=anslen)return ;
    	if(n==1 && !b[t][1]){
    		if(top<anslen){
    			anslen=top;
    			for(int i=1;i<=top;i++)ans[i]=st[i];
    		}
    		return ;
    	}
    	bool flag=1;
    	for(int i=1;i<=n;i++)if(b[t][i]&1){flag=0;break;}
    	if(flag){
    		for(int i=1;i<=n;i++)b[t+1][i]=b[t][i]>>1;
    		n=unique(b[t+1]+1,b[t+1]+n+1)-b[t+1]-1;
    		dfs(t+1,n);
    		return ;
    	}
    	for(int w=-1;w<=1;w+=2){
    		for(int i=1;i<=n;i++)
    			if(b[t][i]&1)b[t+1][i]=(b[t][i]+w)>>1;
    			else b[t+1][i]=b[t][i]>>1;
    		st[++top]=-w*(1<<t);
    		int tmp=unique(b[t+1]+1,b[t+1]+n+1)-b[t+1]-1;
    		dfs(t+1,tmp);
    		top--;
    	}
    }
    int main()
    {
    	freopen("pp.in","r",stdin);
    	freopen("pp.out","w",stdout);
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	n=unique(a+1,a+n+1)-a-1;
    	for(int i=1;i<=n;i++)b[0][i]=a[i];
    	dfs(0,n);
    	printf("%d
    ",anslen);
    	for(int i=1;i<=anslen;i++)printf("%d ",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    python 类C数组的两种形式:list -->内容可变, tuple --->内容不可变
    13、canvas操纵像素数据ImageData
    13、canvas操纵像素数据ImageData
    13、canvas操纵像素数据ImageData
    13、canvas操纵像素数据ImageData
    人工智能工程师学习路线
    人工智能工程师学习路线
    js数组排序和打乱
    js数组排序和打乱
    js数组排序和打乱
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8620208.html
Copyright © 2020-2023  润新知