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

f(x,y)=(x|y)−y按二进制拆位发现对于第i位

若x、y第i位均为1,函数结果第i位为0

若x第i位为0,y第i位为1,函数结果第i位为0

若x第i位为1,y第i位为0,函数结果第i位为1

而对于f(f(…f(f(a1,a2),a3),…an−1),an)无论顺序怎么排 只要第i位为1的个数≥2 n次函数运算后结果第i位为0

证明:

1.若a1第i位为0 那么无论怎么排 n次函数运算后结果第i位为0

2.若a1第i位为1 遇到第二个第i位为1的数后 函数结果第i位为0 之后就变成了第一种情况

故最后答案只取决于第一个数,为第一个数中在n个数中只出现过一次的位

所以为了答案最大,从高位开始贪心,只要该位只出现过一次就退出循环 因为后面位的影响之和显然没有该位大

反思:1.对于涉及位运算且求最大值的题,一般都是从高位到低位贪心,应该果断拆位的

不应该仅按数的顺序来,还要根据二进制位

2.把函数等价为了x-x&y 迭代的时候犯了煞笔错误f(f(x,y),z)=x-x&y-x&y&z了 事实上无论怎么迭代函数结果都只有两项

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    int ans=0;
    for(int i=30;i>=0;i--){
        int cnt=0,pos=0;
        for(int j=1;j<=n;j++)
         if(a[j]&(1<<i)){
             cnt++;
             pos=j;
         }
         if(cnt==1){
         ans=pos;
         break;}
    }
    if(ans==0)for(int i=1;i<=n;i++)cout<<a[i]<<‘ ‘;
    else {
        cout<<a[ans]<<‘ ‘;
        for(int i=1;i<=n;i++)
         if(ans!=i)cout<<a[i]<<‘ ‘;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wyh447154317/p/12289656.html

时间: 2024-10-17 14:36:08

Codeforces Round #618 (Div. 2) C.Anu Has a Function的相关文章

Codeforces Round #618 (Div. 2) E

Problem Codeforces 题目地址 Solution 看完qsc大佬的题解后才发现真的是考场降智啊!!!是真的蠢啊!!! 假设前 \(k-1\) 个数已经通过调整达到了最小字典序,调整成了 \(m\) 块,第 \(i\) 的数(因为都是一样的就叫一块)是 \(x_i\).很显然满足一个条件:\(x_1 < x_2 < ... < x_m\). 现在加入第 \(k\) 个数. 第 \(k\) 个数的左边是 \(x_m\) 这一块,我们只要比较一下 \(a_k\) 和 \(x_m

Codeforces Round #618 (Div. 2)

觉得自己失了智,家里网速太慢了,12分钟之后才卡进去,进去的时候A题过了4k个,B题过了1k个,就感觉很凉 但也不是这次失智的原因……C题因为将10^9看成了10^5之后,数组开了一个15,(应该开30的)然后wa了8发以后,重新读题之后发现了自己失智的情况.这题跟没做一样了 导致DE没有时间理解去做. A 题意: 数组和and积为不能为0 思路: 不能出现0,以及和不能是0 所有最后就是零的个数,如果零的个数+数组和==0的情况需要再加一 1 #include<bits/stdc++.h>

Codeforces Round #618 (Div.1) (Div.2) (CF1299) (CF1300)

A:读进来就把0搞成1,S!=0就直接输出,S=0判一下有没有不是-1的,有不是-1的就+1否则+2. 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 const int N=100005; 9 int n,

Codeforces Round #618 (Div. 1)C(贪心)

把所有数看作N块,后面的块比前面的块小的话就合并,这个过程可能会有很多次,因为后面合并后会把前面的块均摊地更小,可能会影响更前面地块,像是多米诺骨牌效应,从后向前推 1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 double a[1000007]; 5 vector<double>vv[1000007]; 6 int main(){ 7 //ios::sync_wi

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除