CodeForces #647 Div.2 ABC

A

题意描述

问一个数能否通过有限次左移1,2,3位或者右移1,2,3位变成另一个数。
CodeForces #647 Div.2 ABC_第1张图片

思路

只需要知道较小那个数通过左移(扩大为原来的2倍)操作能否变成较大那个数就行了,然后为了使得操作次数最少,所以能移动3次就不移动2次。

import java.util.Scanner;
public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int len = sc.nextInt();
            while(len-->0) {
                long a = sc.nextLong();
                long b = sc.nextLong();
                if(a==b){
                    System.out.println(0);
                }else{
                    long max = Math.max(a,b);
                    long min = Math.min(a,b);
 
                    int count =0;
                    while(min<max){
                        min<<=1;
                        count++;
                    }
                    if(min!=max){
                        System.out.println(-1);
                    }else{
                        int ans = count/3;
                        count%=3;
                        ans+=count/2;
                        count&=1;
                        ans+=count;
                        System.out.println(ans);
                    }
                }
            }
        }
}

B

描述

有一系列数字,能否使每个数字异或同一个数字,使得新数字序列的数字与原来相同(顺序无关)。
CodeForces #647 Div.2 ABC_第2张图片

思路

a异或b = c -> a异或c = b
由于如果想要题目达到的要求,就必然得使得数字之间可以两两转换。
就用一个数字异或其他数字就行了,然后将异或的结果存入一个set中,每次再取共有的部分。最后再根据set取最小那个。如果set为空则说明没有这样的数字
(有点暴力,或许有什么巧妙的办法,但我没想到)

import java.util.*;
public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int len = Integer.parseInt(sc.nextLine());
            while(len-->0) {
                int n = Integer.parseInt(sc.nextLine());
                int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
                Set<Integer> ans = null;
                for(int i=0;i<arr.length;i++){
                    Set<Integer> temp = new HashSet<>();
                    for(int j=0;j<arr.length;j++){
                        if(arr[i]==arr[j]){
                            continue;
                        }else{
                            temp.add(arr[i]^arr[j]);
                        }
                    }
                    if(ans==null){
                        ans = temp;
                    }else {
                        Iterator<Integer> it = ans.iterator();
                        while(it.hasNext()){
                            Integer in = it.next();
                            if(!temp.contains(in)){
                                it.remove();
                            }
                        }
                    }
                }
                if(ans==null||ans.size()==0){
                    System.out.println(-1);
                }else{
                    int min = Integer.MAX_VALUE;
                    for(int a:ans){
                        min = Math.min(min,a);
                    }
                    System.out.println(min);
                }
            }
        }
}

C

描述

给定一个范围0~n ,算出相邻数字之间二进制位数的差异的位数。然后累加起来。
CodeForces #647 Div.2 ABC_第3张图片

思路

没啥好说的,这题是有规律的,规律就是f(n)为第n个数的答案,f(n) = f(n/2)+n.
具体数学上的原理我没想出来,就找到个规律。

import java.util.*;
public class Main{
//long[] ans;
    public static  void main(String[] args){
        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();
        while(n-->0){
            long nn = sc.nextLong();
// ans = new int[nn];
// Arrays.fill(ans,-1);
            System.out.println(getAns(nn));
        }
    }
    private static long getAns(long n){
        if(n==1){
            return 1;
        }
// if(ans[n-1]!=-1){
// return ans[n-1];
// }
        return getAns(n>>1)+n;
    }
}

你可能感兴趣的:(算法/数据结构)