题意:给定一个数组,对于j>i存在arr[i]&arr[j]>arr[i]^arr[j],求共有多少组
思路:对于一个数符合要求的数只有这个数存在于2的n次方到2的n+1次方之前(n为它除2向下取整知道等于1)由于数据较大所以直接写肯定超时,所以需要优化(二分)
代码:
import java.io.*;
import java.math.*;
import java.util.*;
public class Main {
static Scanner sc=new Scanner(System.in);
public static void main(String[] args) {
int n=sc.nextInt();
for(int i=0;i<n;i++) {
show();
}
}
private static void show() {
int n=sc.nextInt();
int arr[]=new int [n];
for(int i=0;i<n;i++) {
arr[i]=sc.nextInt();
}
Arrays.sort(arr);
long s=0;
int a=0,b=0,c=0;
for(int i=0;i<n;i++) {
int l=i,r=n-1;
int mid=0;
if(arr[i]==1) {
a++;
continue;
}
if(arr[i]==2) {
b++;
continue;
}
if(arr[i]==3) {
c++;
continue;
}
while(l<r) {//得到坐标——大于这个数却小于等于他的二倍的数
mid=(l+r+1)/2;
if(arr[mid]>=Math.pow(2,ss(arr[i]))) {
r=mid-1;
}else {
l=mid;
}
}
//System.out.println(arr[i]+" "+arr[r]+" "+r+" "+l);
int x=r;
s+=(long)(x-i);
}
System.out.println(s+(long)a*(a-1)/2+(long)b*(b-1)/2+(long)c*(c-1)/2+(long)b*c);
}
private static int ss(int i) {
int s=0;
while(i!=1) {
i=i/2;
s++;
}
return s+1;
}
}