• [CTSC2017]吉夫特


    Description:

    给定一个序列(a_1,a_2,a_3...a_n)

    求有多少个不上升子序列:

    (a_{b1},a_{b_2}...) 满足 (C_{a_{b1}}^{a_{b2}}*C_{a_{b2}}^{a_{b3}}*.....mod 2 >0)

    输出对(10^9+7)取模的结果

    Hint:

    $ 1 ≤ n ≤ 211985, 1 ≤ ai ≤ 233333​(。所有的) a_i ​$互不相同

    Solution:

    (Lucas)定理:

    $ C_nm=C_{n/2}{m/2} ast C_{n ext{%} 2}^{m ext{%} 2} ext{ % } 2 $

    可见 (C_{n}^m mod 2 ot = 0) 的充要条件是(n,m)转为(2)进制后(m)包含1的位置(n)子集

    为什么?

    好好思考一下(Lucas)的过程,不就可以看成位运算吗?

    一旦有(m>n),则整个式子值为(0)

    故子序列中一个数的后一位(a_j)必须满足 $ a_{i} ext{&} a_{j} = a_{j} $

    枚举二进制位1的子集,直接(dp)就行

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ls p<<1 
    #define rs p<<1|1
    using namespace std;
    typedef long long ll;
    const int mxn=1e6+5,mod=1e9+7;
    int n,ans,a[mxn],f[mxn],rk[mxn];
    
    inline int read() {
    	char c=getchar(); int x=0,f=1;
    	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    	return x*f;
    }
    inline void chkmax(int &x,int y) {if(x<y) x=y;}
    inline void chkmin(int &x,int y) {if(x>y) x=y;}
    
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i) a[i]=read(),rk[a[i]]=i,f[a[i]]=1;
    	for(int i=1;i<=n;++i) 
    		for(int j=(a[i]-1)&a[i];j;j=(j-1)&a[i])	 
    			if(rk[j]>i) f[j]=(f[j]+f[a[i]])%mod;
    	for(int i=1;i<=n;++i) ans=(ans+f[a[i]])%mod;	
    	printf("%d
    ",(ans-n+mod)%mod);
        return 0;
    }
    
    

    g

  • 相关阅读:
    javaDoc 注释规范
    [阿里云] 如何 开放云主机 非80 端口?
    [Go] 跨平台文件系统监控工具 fsnotify 应用举例
    如何利用 jQuery 修改 css 中带有 !important 的样式属性?
    code.google.com/p/log4go 下载失败
    [Go] ok 判断 汇总
    [Go] 编码规范
    《Go语言实战》摘录:7.3 并发模式
    《Go语言实战》摘录:7.2 并发模式
    《Go语言实战》摘录:7.1 并发模式
  • 原文地址:https://www.cnblogs.com/list1/p/10473788.html
Copyright © 2020-2023  润新知