zoukankan      html  css  js  c++  java
  • 【BZOJ4903】

    ​   传送门

    ​   简述题意:给一个序列,询问有多少子序列满足其中不会出现$achoose b$是偶数的情况,其中$a$在$b$前面。

    Solution

    ​   首先探究组合数的奇偶性问题。我们用Lucas定理展开组合数,可以发现一些有趣的性质:

    $$
    {achoose b}={lfloorfrac a 2 rfloorchoose lfloor frac b2rfloor}{amod2 choose bmod 2}
    $$

    ​   后一个括号的值可以直接算:${0choose 0}={1choose 0}={1choose 1}=1,;;{0choose 1}=0$。这相当于$a$和$b$的二进制最末位的某种计算。

    ​   而想象一下第一个括号递归计算的过程,实际上是移除了$a$和$b$的二进制最后一位继续计算。到底层时,其值必定是1。

    ​   所以决定总体奇偶的地方在于第二个括号会不会取0。也就是会不会出现$a$末位为0,$b$末位为1的情况。

    ​   这整一个过程的实质是什么?相当于比较$a$和$b$的每一位对应二进制。一旦出现$a$某一位为0,$b$对应位为1,则整体为偶数。否则整体为奇数。

    ​   再进一步考虑,这种条件,相当于判断$b$的1位集合是否是$a$的1位集合的子集,则整体奇数,否则整体偶数。

    ​   这种关系具有传递性:如果$a$包含$b$,那么$a$包含以$b$开头的合法子序列的每个元素。问题变得非常简单,只需要考虑从哪一个子序列的开头转移:设$f[a]$表示以$a$为开头的子序列个数。枚举$a$的子集$b$,如果$b$在$a$后面,则$f[a]+=f[b]$。

    ​   总时间复杂度为$mathcal O(3^{log_2n})$。

    Code

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20大专栏  【BZOJ4903】span>

    #include <algorithm>
    using namespace std;
    const int N=211990,S=233335,MOD=1e9+7;
    int n,a[N],p[S],f[S];
    inline int (int x,int y){return (x+y)%MOD;}
    inline void upd(int &x,int y){x=plu(x,y);}
    int main(){
      scanf("%d",&n);
      for(int i=1;i<=n;i++) scanf("%d",a+i);
      int ans=-n;
      for(int i=n;i>=1;i--){
        f[a[i]]=1;
        for(int j=(a[i]-1)&a[i];j;j=(j-1)&a[i])
          upd(f[a[i]],f[j]);
        upd(ans,f[a[i]]);
      }
      printf("%dn",plu(ans,MOD));
      return 0;
    }
  • 相关阅读:
    Octet string 解析
    c#之process类相关整理
    C# Process.Start()方法详解(转)
    c语言字符串比较函数strcmp
    C# 启动EXE文件及带启动参数EXE
    C语言中两个相等的char值比较 结果为false
    C语言strcmp()函数:比较字符串(区分大小写)
    char数组与char指针
    (转)在.net中序列化读写xml方法的总结
    PHP实现站点pv,uv统计(三)
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12409906.html
Copyright © 2011-2022 走看看