异或

来源:互联网 发布:专业生物英语软件 编辑:程序博客网 时间:2024/05/01 22:07

给定整数m以及n各数字A1,A2,..An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大于m的有多少个。 

输入描述:
第一行包含两个整数n,m. 第二行给出n个整数A1,A2,...,An。数据范围对于30%的数据,1 <= n, m <= 1000对于100%的数据,1 <= n, m, Ai <= 10^5


输出描述:
输出仅包括一行,即所求的答案
示例1

输入

3 10  6 5 10

输出

2

思路:Brute force肯定TLE,套路肯定是按照一位一位来算

后考虑按位递归,同时对数组进行分类

/* * 还是TLE * 因为这里涉及到了前缀和一位一位的比较 * 很自然想到了Trie,用Trie树优化一下这个过程?? * 但是这里递归的花销是出在哪呢?是每次都要加到一个List花销大了? */public class TLE2 {static int ret = 0;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt(), m = sc.nextInt();int[] a = new int[n];for(int i=0; i<n; i++)a[i]=sc.nextInt();ret = 0;List<Integer> s = new LinkedList<Integer>();for(int i : a)s.add(i);get(a, s, 17, m);System.out.println(ret);}public static void get(int[] a, List<Integer> s, int bit, int m) {List<Integer> s1 = new LinkedList<Integer>(), s0 = new LinkedList<Integer>();int t = (1<<bit);for(int i : s) {if((i & t) != 0)s1.add(i);elses0.add(i);}if(t > m) {ret += s1.size() * s0.size();get(a, s1, bit-1, m);get(a, s0, bit-1, m);} else if((t & m) == t){int tmp = 0;for(int i : s0)for(int j : s1)if((i^j) > m)tmp ++;ret += tmp;}}}


TLE,估计是复制数这一部分开销太大,因为这里涉及到了前缀和一位一位的比较
 * 很自然想到了Trie,用Trie树优化

因为不用新建List添加数字,建树完保持了原有的数据信息

build,在search,遍历一遍数组进行search,这样就可以确定每一步要走的方向

package l5;import java.util.Scanner;/* * Trie树优化,不要新建List添加数字 */public class Main {static long ret = 0;static class Trie {Trie[] next = new Trie[2];int[] cnt = new int[2];}public static void main(String[] args) {ret = 0;Scanner sc = new Scanner(System.in);int n = sc.nextInt(), m = sc.nextInt();int[] a = new int[n];int max = Integer.MIN_VALUE;for(int i=0; i<n; i++) {a[i]=sc.nextInt();max = Math.max(max, a[i]);}int bits = 31;while((max & (1<<bits)) == 0)bits--;Trie root = new Trie();for(int i : a)buildTrie(root, i, bits);for(int i : a) search(root, i, m, bits);System.out.println(ret/2);}private static void search(Trie root, int i, int m, int bits) {if(bits == -1 || root == null)return;int t = (1 << bits), bit = ((i>>bits) & 1);if(t > m) {ret += root.cnt[(1^bit)];search(root.next[bit], i, m, bits-1);} else {search(root.next[(1^bit)], i, m-t, bits-1);}}private static void buildTrie(Trie root, int i, int bits) {if(bits == -1)return;int bit = ((i>>bits) & 1);if(root.next[bit] == null)root.next[bit] = new Trie();root.cnt[bit] ++;buildTrie(root.next[bit], i, bits-1);}}




原创粉丝点击