Codeforces Round #618 (Div. 2).C. Anu Has a Function(c++)

在这里插入图片描述
题目链接
题意大概就是给你一个公式:f(x,y)=(x|y)−y,其中 | 是按为或运算,再给你一个数组an,问怎样排列才能让f(f(…f(f(a1,a2),a3),…an−1),an)得到的结果最大。

拿第一组数据来看
在这里插入图片描述
将其转换成二进制:
4: 100
0: 000
11:1011
6: 110
这样,f(11,6) :
(1011)|(110)-110

(1011)|(110)=1111
1111-110=1001;

f(11,4):
(1011)|(100)-100

(1011)|(100)=1111
1111-100=1011;

由此不难发现,f(x,y)就是先找出y二进制为1的位,再将x中的这些位全部变成0。
所以不难得出思路就是将具有 最高且不重复二进制位的数放在第一个,其它数任意(若无符合条件的,即所有数相同,则任意排列)。
例如 10011 10100 1000,虽然第一二两个都具有最高二进制位,但其重复了,所以应将1000放在第一个。

代码如下

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int we[40],biao[40];//1e9最高是2^30,我们开到40。
void f(int i)//统计每个二进制位出现的个数
{
    int t=a[i],k=0;
    while(t)
    {
        if(t%2!=0)
        {
            we[k]++;//统计个数
            biao[k++]=i;//记录位置
            t/=2;
        }
        else
        {
            t/=2;
            k++;
        }
    }
    return;
}

int main()
{
    int t,n,bb=-1;//bb初始化为-1作用看后面
    cin>>n;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        f(i);//统计二进制位
    }
    for(int i=39;i>=0;i--)//查找每个二进制位
    {
        if(we[i]==1)//出现我们要找的东西
        {
            bb=biao[i];//记录位置
            break;
        }
    }
    int flag=0;//用于输出前置空格
    if(bb!=-1)//判断是否所有数都相同(即是否出现了所需要的数)
    {
    printf("%d",a[bb]);//出现了即输出
    flag=1;//格式
    }
    for(int i=0;i<n;i++)
    {
        if(i==bb)
            continue;
        if(flag)
            printf(" ");
        printf("%d",a[i]);
        flag=1;
    }
    printf("\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值