Anu Has a Function CodeForces - 1300 位运算 + 思维 + 判断进制数

题目地址

思路:

根据题目给出的条件,
f ( f ( … f ( f ( a 1 , a 2 ) , a 3 ) , … a n − 1 ) , a n ) f(f(\dots f(f(a_1, a_2), a_3), \dots a_{n-1}), a_n) f(f(f(f(a1,a2),a3),an1),an)
e p : f ( 11 , 6 ) = ( 11 ∣ 6 ) − 6 = 15 − 6 = 9 ep:f(11, 6) = (11|6) - 6 = 15 - 6 = 9 epf(11,6)=(116)6=156=9
我们可以分析两个数的运算,可知:
11 : 1011 11 :1011 11:1011
6 : 0110 6 : 0110 60110
11 ∣ 6 − 6 = 1001 11 |6 - 6=1001 1166=1001
即:11的二进制中的1与6的二进制的1相同位置的数都被消去了。即11被消去了一位进制。那么我们可以推出,我们要找一个数 a k ak ak,再从 a k ak ak中扣去除 a k ak ak以外的所有数.
可得公式:

f ( x , y ) = f ( x ∣ y ) − y < = > f ( x & ∼ y ) f\left( x,y\right) =f\left( x|y\right) -y<=>f\left( x\& \sim y\right) f(x,y)=f(xy)y<=>f(x&y)

即可得到 ( a k & ( ∼ a n ) & ( ∼ a n + 1 ) & . . . . . . . . ) \left( ak\& (\sim an\right)\& (\sim an +1)\&........) (ak&(an)&(an+1)&........)
我们使 a k ak ak所拥有的进制是唯一且最大的,那么最后留下的数一定是最大的。

步骤

按照分析,先分离每个数的进制,统计每一位出现的次数,如果出现了一次,那么我们保留,并维护一个最大数及下标。剩余的数任意顺序排列即可,因为最终一定会消去 。
AC代码

import java.math.BigInteger;
import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int num[] = new int[100005];
		int cnt[] = new int[105];
	
		int n = cin.nextInt();
		for(int i = 0;i < n;i++)num[i] = cin.nextInt();
		for(int i = 0;i < n;i++) {
			for(int c = 0; c <= 30;c++) {
				if(((num[i] >> c) & 1) == 1) ++cnt[c];///统计每一位出现的次数。
			}
		}
		int idx = 0;
		int sum = 0;
		int ans = 0;
		for(int i = 0;i < n;i++) {
			for(int c = 0; c <= 30;c++) {
				if(((num[i] >> c) & 1) == 1 && cnt[c] == 1) {
					sum += (1 << c);
				}
				
			}
			if(sum > ans) { 
				ans = sum;
				idx = i;
			}
				sum = 0;
		}
		System.out.print(num[idx] + " ");
		for(int i  = 0;i < n;i++) {
			if(i == idx)continue;
			System.out.print(num[i] + " ");
		}
		System.out.println();
		
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值