zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 043B(组合数学)

    先进行一次绝对值差分,把序列中的数都变成 0,1,2 。如果序列中存在 1,答案只能是 0 或 1;如果不存在 1,答案只能是 0 或 2。对于不存在 1 的情况,我们可以将每个数都 除以2,最后再将答案 乘2,这显然是等价的。于是现在答案只能是 0 或 1 ,发现绝对值差分等价于异或。现在问题转化为一个 只包含0和1的序列,每次将相邻两个数异或,求最后剩下的数。那么考虑每个数会被异或几次即可,设序列长度为 n,则位置 i 上的数会被异或 (n−1,i−1) 次。这时候我们还要求出模 2 意义下的组合数,一个简单的方法是计算每个阶乘的分解中 2 的次数,将计算组合数时的除法改为做减法。则对于一个组合数,最后如果剩下的 2 的次数为 0,则说明 mod2=1,否则 mod2=0。对于阶乘的分解,可以先对每个数简单地求出分解中 2 的次数,然后做前缀和即可。时间复杂度 O(n)。

     1 #define HAVE_STRUCT_TIMESPEC
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 int a[1000007],c[1000007];
     5 char s[1000007];
     6 int main() {
     7     ios::sync_with_stdio(false);
     8     cin.tie(NULL);
     9     cout.tie(NULL);
    10     int n;
    11     cin>>n;
    12     cin>>s+1;
    13     --n;
    14     for(int i=1;i<=n;++i)
    15         a[i]=abs(s[i]-s[i+1]);
    16     int flag=0;
    17     for(int i=1;i<=n;++i)
    18         if(a[i]==1)
    19             flag=1;
    20     if(!flag)
    21         for(int i=1;i<=n;++i)
    22             a[i]>>=1;
    23     for(int i=1;i<=n;++i){
    24         int x=i;
    25         while(!(x&1))
    26             ++c[i],x>>=1;
    27         c[i]+=c[i-1];
    28     }
    29     int ans=0;
    30     for(int i=1;i<=n;++i)
    31         ans^=c[n-1]-c[i-1]-c[n-i]?0:(a[i]&1);
    32     if(!flag)
    33         ans<<=1;
    34     cout<<ans;
    35     return 0;
    36 }
  • 相关阅读:
    js选中文本的功能
    css中2端对其布局
    融合渐变轮播图和左右点击轮播图的js
    Hibernate入门一
    SpringDay01
    使用DoTwenn动画的不正常播放
    转载 利用WWW类获取图片并且在unityUGUI的Image中显示
    转载 Unity进阶技巧
    Unity中导入iTween插件问题
    转载 [Unity3D]引擎崩溃、异常、警告、BUG与提示总结及解决方法
  • 原文地址:https://www.cnblogs.com/ldudxy/p/12601250.html
Copyright © 2011-2022 走看看