CF949E Binary Cards 题解

题面

首先发现:一个数最多会出现1次;

然后深入推出:一个数不会既用它又用它的相反数;

这样就可以依次考虑每一位了:
如果所有的数都不含有这一位,那么就直接把所有的数除以2

如果含有,那么就减去这一位的数,再除以2;

2

当含有的时候搜索就可以了;

注意需通过去重来优化dfs,否则会TLE掉;

#include <bits/stdc++.h>
#define N 100010
using namespace std;
int a[N],b[21][N],ans[N],st[N],top=0;
int anss=INT_MAX;
void dfs(int dep,int n){
    if(n<=1&&!b[dep][1]){
        if(top<anss){
            anss=top;
			for(int i=1;i<=top;i++){
				ans[i]=st[i];
			}
        }
        return;
    }
    if(dep>20||top>=anss){
    	return;
    }
    bool flag=1;
    for(int i=1;i<=n;i++){
    	if(b[dep][i]&1){
			flag=0;
			break;
        }
    }
    if(flag){
        for(register int i=1;i<=n;i++){
        	b[dep+1][i]=b[dep][i]/2;
        }
        n=unique(b[dep+1]+1,b[dep+1]+n+1)-b[dep+1]-1;
        dfs(dep+1,n);
        return;
    }
    else{
        for(register int i=1;i<=n;i++){
        	if(b[dep][i]&1){
        		b[dep+1][i]=(b[dep][i]-1)/2;
        	}
            else{
            	b[dep+1][i]=b[dep][i]/2;
            }
        }	            
        st[++top]=1*(1<<dep);
        register int tmp=unique(b[dep+1]+1,b[dep+1]+n+1)-b[dep+1]-1;
        dfs(dep+1,tmp);
        top--;
        for(register int i=1;i<=n;i++){
        	if(b[dep][i]&1){
        		b[dep+1][i]=(b[dep][i]+1)/2;
        	}
            else{
            	b[dep+1][i]=b[dep][i]/2;
            }
        }	            
        st[++top]=-1*(1<<dep);
        tmp=unique(b[dep+1]+1,b[dep+1]+n+1)-b[dep+1]-1;
        dfs(dep+1,tmp);
        top--;
    }   
}
int main()
{
    register 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\n",anss);
    for(int i=1;i<=anss;i++){
    	printf("%d ",ans[i]);
    }
}
相关文章
相关标签/搜索