zoukankan      html  css  js  c++  java
  • CF1438D

    首先,要发现两个性质。
    1.一次操作其实相当于把三个数变为相同的一个数。
    2.每次操作前后整个数列的异或和不变。
    第一个性质比较显然,证明一下第二个性质。
    设原来这三个数分别为 (x)(y)(z)
    操作前,它们的异或和为 (x oplus y oplus z)
    操作后,这三个数都变成了 (x oplus y oplus z)
    它们的异或和仍然为 (x oplus y oplus z)

    先考虑数列长度为奇数的情况。
    首先,把相邻的三个数操作一下,每次操作的起点即为上次操作的终点。
    操作后,整个数列就变为了若干段长度为2的相同的数,以及最后一段长度为3的相同的数。
    这样,把最后一个数拿出来,与前面的每两个相同的数都做一次操作即可。
    操作次数为 (n-2) 次,可以通过。

    接下来,考虑数列长度为偶数的情况。
    如果是有解的,且数列长度为偶数,那么最后整个数列的异或和一定为0。
    根据上面的性质2,可以得到数列操作前的异或和也一定为0,同理,整个数列在每一步操作后的异或和也为0。
    现在已经可以判断无解了。
    若有解,考虑把最后一个数单独拿出来,把前面的 (n-1) 个数按照奇数的做法做一遍。
    因为整个数列在每一步操作后的异或和一定为0,又因为数列的前 (n-1) 个数已经相等了,所以,它们也一定和最后一个数相等。
    操作次数为 (n-3) 次。

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    const int N=1e5+10;
    int n,a[N],sum;
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum^=a[i];
    	if(n%2==0&&sum) puts("NO"),exit(0);
    	if(n%2==0) n--;
    	printf("YES
    %d
    ",n-2);
    	for(int i=1;i<=n-2;i+=2) printf("%d %d %d
    ",i,i+1,i+2);
    	for(int i=1;i<=n-4;i+=2) printf("%d %d %d
    ",i,i+1,n);
    	return 0;
    }
    
  • 相关阅读:
    function与感叹号
    js中的|| 与 &&
    [转] html屏蔽右键、禁止复制
    ExtJS 5.1 WINDOW BLUR
    ExtJS 网页版执行工具
    Excel 随即获得一组数据集中的数据
    [转] Spring Data JPA Tutorial: Pagination
    Set up eclipse for Ext js and spket IDE plugin
    ExtJS Alias, xtype and widget
    ExtJS stores
  • 原文地址:https://www.cnblogs.com/zhs1/p/14266454.html
Copyright © 2011-2022 走看看