zoukankan      html  css  js  c++  java
  • 位运算之巧解

    上班打卡

    Problem Description:

    某公司上班使用打卡制度,员工需要在打卡机器上打入和打出才算上班。每个员工都有自己对应编号K,编号为一个整数(1 <= K <=50000),某天有一员工忘记了一次打出。现在给你当天员工的打卡信息,你能找出该员工的编号吗?

    Input:

    输入包含多组测试,第一行包含数字N,表示公司的人数(1<=N<=50000)。第二行有2N-1个数,两两之间有空格,表示所有员工的打卡记录。输入N为0则退出程序,不做输出。
    

    Output:

    对于每组测试,单独一行输出忘记打卡员工的编号。

    Sample Input:

    4
    10 12 9 12 250 9 10
    

    Sample Output:

    250
    解题思路:给出2n-1个数,其中有n个数出现的次数都为2,剩下的1个数出现的次数为1,要求快速找出这个数。通过异或运算的特点可知,①自己异或本身的值为0,②任何数和0异或都为其本身。因此异或所有出现次数为2的数最终的值为0,那么就只剩下出现次数为1的元素。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,x,ans;
     4 int main(){
     5     while(cin>>n&&n){
     6         n=2*n-1,ans=0;
     7         while(n--){cin>>x;ans^=x;}
     8         cout<<ans<<endl;
     9     }
    10     return 0;
    11 }

    小白刷分记(二)

    Problem Description:

    小白最近刷听力,刷出了一个大麻烦。不知为何刷出了负分,小白只能向大白求助。
    无奈大白翻车了。所以小白向小光师公求助,小光师公说只要你帮我解决了下面这道题目,
    我就帮你刷回正分。无奈小白不会,只能交给聪明的你来解决了。
    数组A中,除了某一个数字x之外,其他数字都出现了三次,
    而x出现了一次。请给出最快的方法找到x。 

    Input:

    先输入n,表示要输入n个数字。( 0< n < 10^8)
    然后输入n个数字m。(-10^8)< m <(10^8)

    Output:

    输出x

    Sample Input:

    10
    2223 1 1 2223 1 -111 1 2223 1 1
    4
    5 5 5 -6

    Sample Output:

    -111
    -6
    解题思路:给出n个数,其中有(n-1)/3个数出现的次数都为3,剩下的1个数出现的次数为1,要求快速找出这个数。考虑每个数的二进制,因为每个数出现的次数都为3,所以32位二进制中每个bit上'1'的统计结果都可以被3整除,否则就是出现次数为1的数在这个bit上贡献出多余的1。因此,将每个数转化成其二进制,并且统计每个bit上1的个数,然后累加某个bit上不能被3整除的十进制数1<<bit,最终即可得到出现次数为1的数字。
    推广一下,所有其他数字出现n(n>=2)次,而一个数字出现1次都可以用这种解法来推导出这个出现1次的数字。

    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,x,ans,bits[32];
     4 int main(){
     5     while(~scanf("%d",&n)){
     6         ans=0;memset(bits,0,sizeof(bits));
     7         for(int i=1;i<=n;++i){
     8             scanf("%d",&x);
     9             if(!x)continue;
    10             for(int j=0;j<32;++j)bits[j]+=((x>>j)&1);//要用右移操作,便于正确计算和避免溢出
    11         }
    12         for(int i=0;i<32;++i)
    13             if(bits[i]%3!=0)ans+=(1<<i);//累加二进制上对应的值
    14         printf("%d
    ",ans);
    15     }
    16     return 0;
    17 }

    NYOJ #744 蚂蚁的难题(一)

    描述

    小蚂蚁童鞋最近迷上了位运算,他感觉位运算非常神奇。不过他最近遇到了一个难题:

    给定一个区间[a,b],在区间里寻找两个数x和y,使得x异或y最大。来,帮帮他吧!

    输入

    有多组测试数据(以EOF结尾)。
    每组数据输入两个数a,b.(0<=a<b<2^63)。

    输出

    输出a到b之间,异或最大的值。

    样例输入

    1 2
    8 9

    样例输出

    3
    1

    解题思路:为了异或得到最大值,我们应选择某两个数的二进制位是互补的,并且其中一个数的二进制最高位的'1'是区间所有数的二进制中相对较高位的'1',这样就能得到全是1的二进制数,其位数为bits,则得到的异或值为2bits-1。于是,通过异或区间左右端点的值a^b可以发现,如果a和b二进制的前几位是相同的,那么在a到b的所有数中,这前几位都不会改变,即无论选什么数进行异或,这前几位都是0,而后面的每个bit里0和1都可能出现,并且一定能找到互补的两个数使其异或后后面的几个bit都是1,这便可得到最大值;同理如果a、b的最高位不同,那么此时取决于b的二进制位数,因为b中某些bit为0的位一定能通过区间中某个数的二进制bit进行'1'互补,即得到全为1的那几位。因此只需要找到a和b的二进制从高位往后数第一个不相同的位,然后如果余下m位,那么答案就是2m-1。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;LL a,b;
     4 LL get_bits(LL x){//得到异或的值的二进制位数
     5     LL bits=1;
     6     while(x>>=1)bits++;
     7     return bits;
     8 }
     9 int main(){
    10     while(cin>>a>>b){
    11         cout<<((1LL<<get_bits(a^b))-1)<<endl;//2^n-1
    12     }
    13     return 0;
    14 }
     
  • 相关阅读:
    Python中append和extend的区别
    python学习 day19
    python学习 day18
    QT下编写使用for循环动态添加刻选择时间类型的按钮(记录一下)
    QT mingw编译器下使用snap7库与西门子200smart-PLC(网口)通信实现代码
    看着挺胖的大胖猫
    QT添加软键盘后,QDialog设置模态后软键盘没响应解决办法
    QT程序打包在别的电脑上运行提示“api-ms-win-crt-runtime-|1-1-0.dll"可能与您正在运行的Window版本不兼容。。。。。
    Qt使用WM_COPYDATA消息进行进程通信
    离线百度地图,QT添加按钮点击切换卫星地图和街道地图
  • 原文地址:https://www.cnblogs.com/acgoto/p/9823298.html
Copyright © 2011-2022 走看看