zoukankan      html  css  js  c++  java
  • CF1438D Powerful Ksenia

    若干个数,每次可以选择三个不同的数,将它们替换成它们的异或和。

    要求在(n)次以内使得所有数相等。

    要求输出方案。

    (nle 10^5)


    想这题时最大的败笔是想着每一位拆开……

    原来跟位运算有关的题目还有不拆位的啊……

    先考虑(n)为奇数的情况:

    假如有数(a,b,b),一次操作可以让它们变成(a,a,a)

    所以考虑先通过一些操作,使得剩下一个数和若干对相同的数,然后就可以(frac{n-1}{2})次做了。

    搞个队列,每次弹出三个数,操作它们,然后将其中两个配对,最后一个丢回去。于是(frac{n-1}{2})次就可以搞完这个过程。

    当为偶数时,由于异或和不变,最后异或和为(0),所以如果一开始异或和不为(0)则无解。

    有解时,对前(n-1)个做以上操作。然后发现剩下那个会magically和前面的一样。

    (因为前面的已经相同,总共的异或和为(0)。)


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define N 100005
    int n;
    int a[N];
    queue<int> q;
    queue<pair<int,int> > p;
    void work(int n){
    	for (int i=1;i<=n;++i)
    		q.push(i);
    	printf("YES
    %d
    ",n-1);
    	while (q.size()>1){
    		int x=q.front();q.pop();
    		int y=q.front();q.pop();
    		int z=q.front();q.pop();
    		printf("%d %d %d
    ",x,y,z);
    		a[x]=a[y]=a[z]=a[x]^a[y]^a[z];
    		p.push(make_pair(x,y));
    		q.push(z);
    	}
    	int z=q.front();
    	while (!p.empty()){
    		printf("%d %d %d
    ",z,p.front().first,p.front().second);
    		p.pop();
    	}
    }
    int main(){
    	scanf("%d",&n);
    	int x=0;
    	for (int i=1;i<=n;++i)
    		scanf("%d",&a[i]),x^=a[i];
    	if (n&1)
    		work(n);
    	else{
    		if (x)
    			printf("NO
    ");
    		else
    			work(n-1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    判断添加用户名的唯一性
    显示用户登录用户名
    security安全框架,用户登录安全认证与退出
    mybatis分页助手分页
    javaWeb删除一条及多条数据
    javaWeb手动分页步骤
    自定义格式日期
    iOS开发UI篇—懒加载
    IOS-添加分段控件SegmentControl
    iOS设计模式——Category
  • 原文地址:https://www.cnblogs.com/jz-597/p/13979516.html
Copyright © 2011-2022 走看看