zoukankan      html  css  js  c++  java
  • zzuli1519: 小P参加相亲大会(异或)

    http://acm.zzuli.edu.cn/problem.php?id=1519

    题目描述

    小P最近人生得意,去参加了一次相亲大会,相亲大会上每个人有一个密码牌(密码牌上的密码是一个正整数m,m<231 ),相互之间在交流之前先交换密码牌,密码牌上的密码可能相同,也可能不同,如果相同,两人牵手离开,如果不保同,各自再寻找下一位,保证最后只有1个人或2个人留下来。
     

    输入

    第一行两个数 n,k (n≤3000000,1≤k≤2),n表示参加相亲大会的人数,接下来 n行每行一个正整数表示相亲大会上每一个人的密码,k表示最后留在相亲大会的人数。

    输出

    从小到大输出一行 k个数,表示相亲不成功留在相亲大会人的密码,中间用空格分隔。

    样例输入 Copy

    3 1
    2
    2
    2

    样例输出 Copy

    2

    提示

    对于40% 的数据,保证 k=1。

    对于20%的数据,保证n≤100

    对于100%的数据,保证 n≤3000000,ai<2^{31}

    异或就是把两个数转换成二进制,进行相同位上的运算,

    相同为0,不同为1

    也就是说相同的数异或为0,与0异或为本身。

    a^a=0, a^0=a;

    如果是在给出的数中找出一个出现奇数次的数,只需要把所有的数异或剩下最后的那个数就是答案。

    但是这道题有两个数的情况,下面说的是两个数的情况:

    还是先把所有的数异或一下,最后得出的数是两个应该输出的两个数异或的结果k。

    把这个数转换成二进制,找出为1的位,要输出的两个数这个位一个为0,一个为1。

    再遍历一次数组,把相应位上为1(或0)的数再异或一遍,最后得到两个数中的一个a。

    再将k和a异或得到另一个答案b。

    用到的公式:

    k=a^b;

    a=k^b=a^b^b

    b=k^a=a^b^a

    #include<stdio.h>
    #define N 3000020
    int a[N];
    int main()
    {
    	int n,k,i,ans=0,r,t;
    	scanf("%d%d", &n, &k);
    	for(i=0; i<n; i++)
    	{
    		scanf("%d", &a[i]);
    		ans^= a[i];
    	}
    	if(k == 1)
    		printf("%d
    ", ans);
    	else
    	{
    		r=ans;
    		t=1;
    		while(!(r%2))
    		{
    			r/=2;
    			t*=2;
    		}
    		r=ans;
    		for(i=0; i<n; i++)
    			if((a[i]/t)%2)
    				ans^= a[i];
    		printf("%d ", ans);
    		printf("%d
    ", ans^r);
    	}
    	return 0;
    } 
  • 相关阅读:
    codeforces431C
    codeforces158C
    codeforces570C
    codeforces472C
    codeforces401C
    codeforces630C
    codeforces581C
    校内题目腐草为萤
    校内题目大美江湖
    洛谷P3370 && 字符串哈希讲解
  • 原文地址:https://www.cnblogs.com/zyq1758043090/p/11852783.html
Copyright © 2011-2022 走看看