N个数最少能由多少个数异或产生

题目描述:你现在想绘制一幅画,但是你现在没有足够颜色的颜料。为了让问题简单,我们用正整数表示不同颜色的颜料。你知道这幅画需要的n种颜色的颜料,你现在可以去商店购买一些颜料,但是商店不能保证能供应所有颜色的颜料,所以你需要自己混合一些颜料。混合两种不一样的颜色A和颜色B颜料可以产生(A XOR B)这种颜色的颜料(新产生的颜料也可以用作继续混合产生新的颜色,XOR表示异或操作)。本着勤俭节约的精神,你想购买更少的颜料就满足要求,所以兼职程序员的你需要编程来计算出最少需要购买几种颜色的颜料?(输出最少需要在商店购买的颜料颜色种数,注意可能购买的颜色不一定会使用在画中,只是为了产生新的颜色)

题目理解:输入n个数,对应题目的n个颜色将,两种颜色混合会产新的颜色,这些数之间进行多次xor(异或操作),其中一个数可能被xor多次,看最后能剩余多少不重复的数,输出数量即可。 且最高位一样的颜色不可能是混合而来必须得单独买,但是相对数字比较小的可以由数字大的混合过来的

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
long color[60];
 
//快排,升序(从小到大)
void quicksort(long *arr,int start,int last){
    
    
    if(start>=last){
    
    
        return ;
    }
    int left=start,right=last,pos=start+1;
    long pivotValue=arr[start],tmp=0;
    while(left!=right){
    
    
        if(arr[pos]>pivotValue){
    
    
            //由于两个数进行了交换,pos位置的值是新值,所以不用后移
            tmp=arr[right];
            arr[right--]=arr[pos];
            arr[pos]=tmp;
        }else{
    
    
            arr[left++]=arr[pos];
            pos++;
        }
    }
    arr[left]=pivotValue;
    quicksort(arr,start,left-1);
    quicksort(arr,left+1,last);
}
 
int GetHighestBitPosition(long num){
    
    
    int cnt=0;
    while( num > 0 ){
    
    
        num >>= 1;
        cnt++;
    }
    return cnt;
}
 
int find(long arr[],int length,long value){
    
    
    for(int i = 0 ; i < length ; i++ ){
    
    
        if(value == arr[i]){
    
    
            return 1;
        }
    }
    return 0;
}
 
int main(){
    
    
    int colorNum;
    int newColor;
    int result,remainNum,cmpSubscript,endSubscript;
    scanf("%d",&colorNum);
    if( colorNum <= 0){
    
    
        return -1;
    }
    if(colorNum<=2){
    
    
        printf("%d\n",colorNum);
    }
    remainNum = colorNum;
    for(int  i= 0;i<colorNum;i++){
    
    
        scanf("%ld",&color[i]);
    }
    quicksort(color,0,colorNum-1);
    cmpSubscript = colorNum-2 ;
    endSubscript = colorNum-1 ;
    result = 0;
    while( remainNum > 2){
    
    
        //如果最高为相等,就可以把两个大数相异或变成小数。然后两个小数再异或编程更小的数,然后就一直循环。看看有多少种颜色是可以被消去的
        if(GetHighestBitPosition(color[endSubscript]) == GetHighestBitPosition(color[cmpSubscript]) ){
    
    
            newColor = color[endSubscript] ^ color[cmpSubscript];
            //如果在色板中没有找到该颜色,就把该颜色添加到色板中
            if( 0 == find(color,remainNum,newColor) ){
    
    
                color[remainNum++] = newColor;
                quicksort(color,0,remainNum-1);
                cmpSubscript++;
                endSubscript++;
            }
        }else{
    
    
            //记录的是有多少种不可以依靠大数变小数的方式消去的颜色的种数
            result++;
        }
        //对于一种颜色而言,要么可以变成小数被消去,要么不可以被消去。两种情况上面都已经考虑了,所以可以把这种颜色在色板中排除
        color[remainNum--] = 0;
        endSubscript = cmpSubscript;
        cmpSubscript--;
    }
    printf("%d\n",result+remainNum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44910502/article/details/112552688