• Codeforces 449D Jzzhu and Numbers


    http://codeforces.com/problemset/problem/449/D

    题意:给n个数,求and起来最后为0的集合方案数有多少

    思路:考虑容斥,ans=(-1)^k*num(k),num(k)代表至少有k个数字and起来为1的方案数,那么怎么求num呢?

    考虑and起来至少为x的方案数:那么一定是2^y-1,其中y代表有多少个数&x==x,问题就变成有多少数"包含"了某个数(二进制下),用dp解决这个问题:如果某一位数字是1,那么它一定能转移到它不是1的那个位置。

    即:f[i]+=f[i|(1<<j)]

    注意循环,如果两层的循环换一下位置就会重复计数了。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    const ll Mod=1000000007;
    ll f[2000005],bin[2000005];
    int n;
    int read(){
        int t=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
        while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
        return t*f;
    }
    void solve(){
       for (int j=0;j<20;j++)
        for (int i=0;i<=1000000;i++)
            if ((1<<j)&i) (f[i^(1<<j)]+=f[i])%=Mod;
        ll ans=0;        
        for (int i=0;i<=1000000;i++){
            int cnt=1;
            for (int j=0;j<20;j++)
                if ((1<<j)&i) cnt=-cnt;
            ans=((ans+(cnt*(bin[f[i]]-1)%Mod))%Mod+Mod)%Mod;        
        }        
        printf("%I64d
    ",ans);
    }
    int main(){
        n=read();
        bin[0]=1;
        for (int i=1;i<=1000000;i++) bin[i]=(bin[i-1]*2)%Mod;
        for (int i=1;i<=n;i++) f[read()]++;
        solve();
    }
  • 相关阅读:
    NYoj 素数环(深搜入门)
    深搜和广搜
    hdu 3449 (有依赖的01背包)
    hdu 1712 (分组背包入门)
    sql数据库常用语句总结
    常用工具和API的网站收集
    23种设计模式
    sql 联合查询并更新
    sql 去除重复记录
    读<你必须知道的.NET>IL指令笔记
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5662875.html
Copyright © 2020-2023  润新知