zoukankan      html  css  js  c++  java
  • ZOJ

    ZOJ - 3591 NIM

      题目大意:给你n,s,w和代码,能生成长度为n的序列,问异或和不为0的子序列有多少个?

      这是个挂羊头卖狗肉的题,和NIM博弈的关系就是要异或和不为0,一开始以博弈甚至循环节的去想这题,完全跑偏了。其实主要还是一个异或和,我们看一组数2 3 2 3 2 3 2,我们像前缀和一样去处理

    数           2        3       2       3        2      3       3

    异或和    2        1       3       0        2      1       2

    位置        1        2       3       4        5      6        7

      我们可以发现位置1到位置5的异或结果是一样的都是2,这能说明什么呢,说明位置1到位置4的异或结果为0,位置4的异或和就是0,这很明显。再来看位置2到位置6的他们异或结果都是1,为什么呢?因为位置2到位置5的异或结果0,中间的异或结果为0,所以从位置2到位置6的异或结果才会相同。我们来看异或和结果一样的位置1,5,7,可以发现它们异或和相等,然后和位置已经没有太大关系,因为异或和相同,说明两个位置中间的异或结果为0。那每两个相同异或和结果的位置就决定了一个为0的子序列。所以我们只需要排个序,然后统计相同异或和的长度len,然后两两组合就是len*(len-1)/2个序列为0,我们只要用总结果n*(n+1)/2减去这个组合的个数就可以得到答案了,还有就是异或和已经等于0的位置就像上面的位置4,他们相当于从位置0(最初)到当前位置的序列,这也要减去。详情见代码。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 #define ll long long
     5 const int N=101108;
     6 ll n,s,w,a[N],sum[N];
     7 void init()
     8 {
     9     ll g=s;
    10     sum[0]=0;
    11     for (int i=1;i<=n;i++) 
    12     { 
    13         a[i]=g;
    14         sum[i]=sum[i-1]^a[i];//前缀异或和 
    15         if(a[i]==0)
    16             a[i]=g=w;
    17         if(g%2==0)
    18             g=g/2;
    19         else           
    20             g=(g/2)^w;
    21     }
    22     sum[n+1]=-1;//为了把最后的也统计上,加上个终止条件 
    23 }
    24 int main()
    25 {
    26     int t;
    27     scanf("%d",&t);
    28     while(t--)
    29     {
    30         scanf("%lld%lld%lld",&n,&s,&w);
    31         init();
    32         sort(sum+1,sum+1+n);//把前缀异或和排个序,使相同的在连续区间 
    33         ll ans=n*(n+1)/2;
    34         for(ll i=1,j=1;i<=n+1;i++)
    35         {
    36             if(sum[i]==0)//已经是0了减去 
    37                 ans--;
    38             if(i>1&&sum[i]!=sum[i-1])//减去中间相同区间的组合 
    39             {
    40                 ans-=(i-j)*(i-j-1)/2;
    41                 j=i;
    42             }
    43         }
    44         printf("%lld
    ",ans);
    45     }
    46     return 0;
    47 }
    前前后后

      这题给了我一个很好的启发,也是在敲板子套模板多了之后给我提了个思考,要变通,要去思考问题。

  • 相关阅读:
    VUE 源码工具
    elasticsearch 根据主键_id更新部分字段
    Linux下解压文件到其他目录
    centos 7 安装docker
    英语阅读
    将Word文件上传到博客园
    kafka
    ubantu批量下载依赖包+apt命令list
    llvm.20.SwiftCompiler.Compiler-Driver
    Java获取resources文件夹下properties配置文件
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/10526848.html
Copyright © 2011-2022 走看看