zoukankan      html  css  js  c++  java
  • CodeForces 449D Jzzhu and Numbers 【DP+容斥】

    题意

    给定一个n元集,元素为ai,求其有多少个子集,使得其中的元素ai1,.....aik满足
    ai1&ai2&&aik=0
    (1n,a106)

    分析

    要是n和a的范围小一些自然可以直接用01背包做,然而这里a与n都达到了1e6的范围,则要另寻他法。
    先求有多少种情况使得与出来的结果不为0,考察有多少元素在某些二进制位上为1,则它们与出来在这些位上也必然为1。 令函数f(x)为满足ai&x=x的a的个数。 这里的x就是一个bitmask,满足ai&x=x的a,也就意味着这些a在x为1的那些二进制位上为1。
    那么有了f(x)以后,就可以用容斥原理求出有多少种使得结果不为1的情况。再令g(x)为x的二进制位中1的个数,那么所有结果不为1的情况:

    x=1220(1)g(x)+1(2f(x)1)

    注意2的幂要减一,因为不能一个也不选。x的上限取到2e20,刚好比1e6大,能满足所有位。
    这时再求为0的情况:
    2nx=1220(1)g(x)+1(2f(x)1)

    =x=1220(1)g(x)(2f(x)1)

    现在问题在于如何快速求得f(x)。先将每个a和x分为前k位和后20-k位两部分,A0表示某个a的前k位,A1表示后20-k位,同理有X0X1
    设状态:

    dp[x][k]A0&X0A1=X1a

    转移方程:
    dp[x][k]={dp[x][k1]+dp[x+2k][k1]xk0dp[x][k1]xk1

    显然dp[x][20]=f(x)

    AC代码

    //CodeForces 449D Jzzhu and Numbers
    //AC 2017-1-19 14:21:28
    //DP, Inclusion-exclusion
    #include <bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    const int maxn=1e6+100;
    
    int n;
    int a[maxn];
    int dp[(1<<21)][21];
    
    long long powmod(long long x,long long y,long long m)
    {
        long long z=x%m;
        if(!y)
            return 1;
        if(y&1)
            return z*powmod(z*z,(y-1)/2,m)%m;
        else
            return powmod(z*z,y/2,m)%m;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<n;++i)
            scanf("%d",a+i);
        for(int i=0;i<n;++i)
            ++dp[a[i]][0];
        for(int i=1;i<21;++i)
        {
            for(int j=0;j<(1<<21);++j)
            {
                if((j>>(i-1))&1)
                    dp[j][i]=dp[j][i-1];
                else
                    dp[j][i]=dp[j][i-1]+dp[j+(1<<(i-1))][i-1];
            }
        }
        long long ans=0;
        for(int i=0;i<(1<<21);++i)
        {
            long long cur=powmod(2,dp[i][20],mod)-1;
            if(__builtin_popcount(i)&1)
                cur=-cur;
            ans+=cur+mod;
            ans%=mod;
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    适用于 Laravel 的内部收单模块
    适用于 Laravel API 的签名看守器
    适用于 Laravel 的百度搜索推送
    适用于Yii2的千万级数据秒分页
    PostMan 代理的一个大坑
    PHP 各种金融利息的计算方法
    软件工程之UML建模课
    Windows 通过 cmd 得到域名的dns
    在windows下,通过git-bash里的ssh,远程登陆虚拟机里的linux
    Java常见缩写
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580573.html
Copyright © 2011-2022 走看看