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;
    }
    
  • 相关阅读:
    Checking Types Against the Real World in TypeScript
    nexus pip proxy config
    go.rice 强大灵活的golang 静态资源嵌入包
    几个golang 静态资源嵌入包
    rpm 子包创建学习
    Rpm Creating Subpackages
    ava 类似jest snapshot 功能试用
    ava js 测试框架基本试用
    The Architectural Principles Behind Vrbo’s GraphQL Implementation
    graphql-compose graphql schema 生成工具集
  • 原文地址:https://www.cnblogs.com/jz-597/p/13979516.html
Copyright © 2011-2022 走看看