题目描述
输入描述:
第一行为绘制这幅画需要的颜色种数n (1 ≤ n ≤ 50) 第二行为n个数xi(1 ≤ xi ≤ 1,000,000,000),表示需要的各种颜料.
输出描述:
输出最少需要在商店购买的颜料颜色种数,注意可能购买的颜色不一定会使用在画中,只是为了产生新的颜色。
输入
3 1 7 3
输出
3
java代码:
package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class Color {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
ArrayList<Integer> list=new ArrayList<Integer>();
int n=sc.nextInt() //定义需要多少种颜色
for(int i=0;i<n;i++)
{
list.add(sc.nextInt());
}
Collections.sort(list);//首先对列表中的数字进行排序
int result=0;
int endNumber=list.size()-1; //endNumber、preEndNumber始终指向的是最后一位和倒数第二位数
int preEndNumber=endNumber-1;
while(list.size()>2)
{
int temp;
//如果两者的最高位相同,说明最高位可以消掉,如果两者的最高位相同,说明最高位可以消掉
if(getHight(list.get(endNumber))==getHight(list.get(preEndNumber)))
{
temp=list.get(endNumber)^list.get(preEndNumber);
// 因为现在 xor 的是两个最大的数,而且最高位已被消掉,所以 xor 得到的结果一定比这两个数小
// 如果 temp 这个 比最大两个数小的 数没有被找到,则将 temp 加到 colors 数组中,进行再次 xor
if(!list.contains(temp))
{
list.add(temp);
endNumber++;
preEndNumber++;
Collections.sort(list);
}
}else
{
result++;
}
// 如果两者最高位不同,说明已经所有数的最高位已经只有最大的那个数是 1 了,这样它已经不可能被消掉了,结果+ 1
// 如果两个最大数的最高位可以消掉,那么消除之后,最大数已被消掉,没有用了
// 如果两个最大数的最高位不可以消掉,那么结果+ 1 ,最大数也没有用了。
list.remove(list.size()-1);
endNumber=preEndNumber;
preEndNumber--;
}
System.out.println(list.size()+result);
}
//判断最高位的函数
public static int getHight(int num)
{
int k=0;
while(num>0)
{
num>>=1;
k++;
}
return k;
}
}
注释:最大两个数最高位不同(也即最左边1的位数不同),则大的最左边位置为1,小的相应位为0,显然最大的是不能被合成的(除自己外,再没有相应位为1的啊),而且它也不能合成其它数(其它数相应位都为0啊),故此时将最大数直接丢弃,所需的颜料数加一。若最高位相同,则对两数异或,合成的数(一定比当前合成它的两数小)若不存在,则添加入初始颜料数中并排序(以待合成其它数),无论合成的数是否存在,都要删掉最后一个数,因为它是可以被合成的(A(最大)^B(次大)=C(合成数),B^C=A(最大数))。总之最后一个数(排序后)每比操作一次都要舍弃掉