• CodeForces 449D(容斥,DP


    题目:给出N<=10^6)个数,每个数<=10^6. 从中选出至少1个数,易知有2^N-1种不同方案。那么在这些方案中,有多少种满足选出的所有数AND起来为0呢?

    我是不会做的,找了一个题解然而看了好久看不懂,后来看了下官方题解发现我看得那个有个地方写错了。。。。

    官方题解如下:

    Firstly, we can use inclusion-exclusion principle in this problem. Let f(x) be the count of number i where Ai&x = x. Let g(x) be the number of 1 in the binary respresentation of x. Then the answer equals to .

    Now the task is to calculate f(x) for every integer x between 0 and 220. Let fk(x) be the count of number i where Y0&X0 = X0 and X1 = Y1 (they are defined below).

    We divide x and Ai into two parts, the first k binary bits and the other 20 - k binary bits. Let X0 be the first part of x and X1 be the second part of x. Let Y0 be the first part of Ai and Y1 be the second part of Ai.

    We can calculate fk(x) in O(1):

    The problem can be solved in O(n * 2n) now (n = 20 in this problem).

    做的时候作死把pow函数里的乘数写成了int。。。。总是犯这种错误。。。我发誓以后不用int做数学题了。。。。然后,对于这个dp的思路究竟是咋想出来的还是没有啥头绪,估计下次碰到这种提还是不会吧。。。每次都能看懂题解然后下次又不会了啊。。。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<functional>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int maxv=1e5+30;
    const ll mod=1000000007;
    int N;
    int a[1<<20];
    int dp[22][1<<20];
    int fpow(int x,ll p){
        int ans=1;
        ll xx=x;
        while(p>0){
            if(p&1)
            ans=(xx*ans)%mod;
            xx=(xx*xx)%mod;
            p>>=1;
        }
        return ans;
    }
    void add(int &a,int b){
        a=((a+b)%mod+mod)%mod;
    }
    int main(){
        ///freopen("in","r",stdin);
        cin>>N;
        for(int i=0;i<N;i++) scanf("%d",&a[i]);
        sort(a,a+N);
        for(int i=0;i<N;i++){
            if(a[i]&1) add(dp[0][a[i]],1),add(dp[0][a[i]-1],1);
            else add(dp[0][a[i]],1);
        }
        for(int i=1;i<20;i++){
            for(int j=1;j<(1<<20);j++){
                if(j&(1<<i)) add(dp[i][j],dp[i-1][j]);
                else add(dp[i][j],dp[i-1][j]),add(dp[i][j],dp[i-1][j+(1<<i)]);
            }
        }
        int ans=fpow(2,N)-1;
            for(int j=1;j<(1<<20);j++){
                int bb=__builtin_popcount(j);
                if(bb%2) add(ans,-fpow(2,dp[19][j])+1);
                else add(ans,fpow(2,dp[19][j])-1);
            }
        cout<<ans<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    windows利用net use删除smb连接
    用jquery的ajax功能获取网站alexa的方法
    11对于Web开发人员和设计师非常有用的在线工具
    Php获取Alexa排行统计
    php获取alexa世界排名值的函数
    26个免费矢量图片免费下载
    对makefile中双冒号规则的学习
    对makefile中 $*的理解
    GNU make manual 翻译(七十三)
    对makefile 中的 静态模式规则的理解
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4523419.html
Copyright © 2020-2023  润新知