第一行为绘制这幅画需要的颜色种数n (1 ≤ n ≤ 50) 第二行为n个数xi(1 ≤ xi ≤ 1,000,000,000),表示需要的各种颜料.
输出最少需要在商店购买的颜料颜色种数,注意可能购买的颜色不一定会使用在画中,只是为了产生新的颜色。
3 1 7 3
3
import java.util.*; import java.io.*; public class Main { /** *矩阵论中的知识表明,最大线性无关组是解的最基本的形式。 *这个题目类似于求矩阵的最大线性无关组,用高斯消元法就可以了,正向算一遍即可,反向不用计算(我们只关心无关组的向量个数,不关心具体解的形式)。 *多元方程,我们从左到右不为零开始消元,对于二进制数,那就是从大的数开始就可以了。 *用一个函数判断每一位是否为零,为零才消元。遍历的时候注意方程有几个,我们每次遍历的目标是消灭一列的1,使每一列最多1个一, *但是方程不够的时候,就不必向下消了,已经可以结束了。 */ public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine().trim()); int[] arrColor = new int[n]; String[] arrInput = br.readLine().trim().split(" "); for (int i=0; i<n; i++) { arrColor[i] = Integer.parseInt(arrInput[i]); } Arrays.sort(arrColor);//排序 int computLoopCnt = 0;//记录循环的个数 for (int i=31; i>=0; i--) {//遍历每一位,最大的数的该位为零就跳过 int row = (n - 1) - computLoopCnt; if (row <= 0) {//如果行数不够了,直接停止 break; } if (isNbitIsOne(arrColor[row],i)) {//判断该为是否为零 computLoopCnt++; for (int j=row-1; j>=0; j--) { if (isNbitIsOne(arrColor[j],i)) { arrColor[j] = arrColor[row] ^ arrColor[j]; } } Arrays.sort(arrColor, 0, row );//每次计算后排序,因为异或后可能变大,要正确找到最大的 } } int baseNum = 0; for (int i=0; i<n; i++) { if (arrColor[i] != 0) { baseNum++; } } System.out.println(baseNum); } public static boolean isNbitIsOne(int a, int n) {//判断第n位(顺寻方向:自右向左)是否为零 if (n > 32) { throw new IllegalArgumentException(); } int test = 1 << n; boolean isOne = false; if (test == (a & test)) { isOne = true; } return isOne; } }
/** * 思路:前面高票答案都说了,其实题目的本质是求矩阵的秩,矩阵中的每个 * 向量即为每个数的二进制形式。但是矩阵秩的求法是加减运算(高斯消元法), * 而此题不同之处在于:以异或运算来代替加减运算。 */ import java.util.*; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNext()) { int count = in.nextInt(); int[] array = new int[count]; for (int i = 0; i < count; i++) array[i] = in.nextInt(); Arrays.sort(array); for (int i = count - 1; i >= 0; i--) { for (int j = i - 1; j >= 0; j--) if ((array[i] ^ array[j]) < array[j]) array[j] ^= array[i]; } int res = 0; for (int i = 0; i < count; i++) { if (array[i] != 0) res++; } System.out.println(res); } } }
//化上三角,求01矩阵的秩,只是操作是异或 //O(n^2) 每次取最大的数换到上面,然后下面的数去清除当前的最高位,再取清除后数中的最大,置换循环 import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); while(input.hasNext()){ int n = input.nextInt(); int[] a = new int[n]; int maxi = 0; for(int i=0;i<n;i++){ a[i] = input.nextInt(); if(a[maxi]<a[i]) maxi = i; } swap(0,maxi,a); for(int b=0;b<n-1;b++){ maxi = -1; for(int i=b+1;i<n;i++){ if((a[i]^a[b])<a[i]){ a[i] = a[i]^a[b]; } if(maxi==-1||a[maxi]<a[i]) maxi = i; } swap(b+1,maxi,a); } int ans = 0; for(int i=0;i<n;i++){ //System.out.println(Integer.toBinaryString(a[i])); if(a[i]>0) ans++; } System.out.println(ans); } } public static void swap(int i,int j,int[] a){ int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } }
/** * 综合了以上很多的见解 * 数组从小到大排列,从最下面一行开始,每次消去最高位的1,比如A行的系数减去B行,直接A = A^B就行 */ import java.util.*; public class Main1 { public static void main(String[] args) { Scanner scan = new Scanner(System.in); while(scan.hasNext()){ int n = scan.nextInt(); int[] col = new int[n]; for(int i=0; i<n; i++){ col[i] = scan.nextInt(); } Arrays.sort(col); int count = 0; for(int i=n-1; i>=0; i--){ for(int j=i-1; j>=0; j--){ /** * 如果两者的最高位相同,说明最高位可以消掉, * 将两者 xor ,或者说将矩阵两行相减消掉最高位 */ if(highbit(col[i]) == highbit(col[j])){ /** 如果两个最大数的最高位可以消掉,那么消除之后,最大数已被消掉,没有用了 如果两个最大数的最高位不可以消掉,那么结果+ 1 ,最大数也没有用了。 */ col[j] = col[j] ^ col[i]; } } Arrays.sort(col); } for(int i=0 ;i<n;i++) if(col[i] !=0){ count ++; } System.out.println(count); } } public static int highbit(int x){ /*一个数是由32位表示的,那么我们可以把一个数看成是32维空间的一个向量。最后形成了一个n*32的矩阵*/ for(int i=31;i>=0;i--) { //相同则结果为0,不同则结果为1 int m = (x>>i)&1; if(m != 0) return i+1;//找到高位,而不是i } return 0; } }
import java.io.*; import java.util.*; public class Main { public static void main(String[] args) { mixedColour(); } public static void mixedColour() { Scanner scanner=new Scanner(System.in); int num=scanner.nextInt(); Integer[] colour=new Integer[num]; int index=0; //注意不能写成 scanner.hasNextInt() && index<num,这样的话会先执行scanner.hasNextInt(),然后一直等待输入 while(index<num && scanner.hasNextInt()) { colour[index]=scanner.nextInt(); index++; } HashSet<Integer> allColour=new HashSet<Integer>(); int count=0; for(int i=0;i<colour.length;i++) { if(allColour.contains(colour[i])) { continue; } HashSet<Integer> tmpColour=new HashSet<Integer>(); tmpColour.add(colour[i]); for(int tmp:allColour) { tmpColour.add(tmp^colour[i]); } allColour.addAll(tmpColour); count++; if(allColour.containsAll(Arrays.asList(colour))) { System.out.println(count); break; } } } } 各位大神可以看看我这思路对吗?本地调试可以通过但是牛客网上超时,如果思路对的话有没有啥子优化方法呢?