zoukankan      html  css  js  c++  java
  • BZOJ5262(容斥)

    题目描述
    听着自己美妙的曲子,小Z进入了梦乡。在梦中,小Z仿佛又回到了自己纵横考场的年代。在梦中,小Z参加了一场
    考试,这场考试一共有n道题,每道题的最终得分都是一个大于等于0的整数。然而醒来后,小Z忘记了自己每道题
    的得分。他只记得自己计算过m次一些题目的分数和,每道题都被计算过,并且只被计算过一次。除此之外他还记
    得其中t道题的满分分别是多少(一道题的得分不会超过满分)。现在小Z想知道他这场考试有多少种得分情况(至
    少有一道题的得分不同就算不同的情况),因为这个答案可能很大,你只需要输出答案对1,000,000,007取模后的
    结果即可。
    题解
    看到t比较小,就想到容斥。
    我是把每一次求和分开算,最后乘起来,每次找出这次求和的所有限制,然后就2^n枚举限制的选择情况,用C(n+m-1,m-1)算方案数。
    代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define N 2000009
    using namespace std;
    typedef long long ll;
    const int maxn=2000000;
    vector<ll>vec[N];
    ll jie[N],ni[N],ans,k[N],sum[N],n,m,p[N],t,num[N];
    const int mod=1e9+7;
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    inline ll power(ll x,int y){
        ll ans=1;
        while(y){if(y&1)ans=ans*x%mod;x=x*x%mod;y>>=1;}
        return ans;
    }
    inline ll C(int x,int y){if(x<y)return 0;return jie[x]*ni[y]%mod*ni[x-y]%mod;}
    void dfs(int s,int i,int num,int k,int q,ll sum){
        if(i>k){
            if(s&1)ans-=C(sum-num+q-1,q-1);
            else ans+=C(sum-num+q-1,q-1);
            ans=(ans%mod+mod)%mod;
            return;
        }
        dfs(s+1,i+1,num+p[i]+1,k,q,sum);dfs(s,i+1,num,k,q,sum);
    }
    int main(){
    //    freopen("Equation.in","r",stdin);
    //    freopen("Equation.out","w",stdout);
        n=rd();m=rd();int x,y;
        jie[0]=1;for(int i=1;i<=maxn;++i)jie[i]=jie[i-1]*i%mod;ni[maxn]=power(jie[maxn],mod-2);
        for(int i=maxn-1;i>=0;--i)ni[i]=ni[i+1]*(i+1)%mod;
        for(int i=1;i<=m;++i){
            k[i]=rd();
            for(int j=1;j<=k[i];++j)x=rd(),vec[i].push_back(x);sum[i]=rd();
        }
        t=rd();
        memset(num,-1,sizeof(num));
        for(int i=1;i<=t;++i){
            x=rd();y=rd();num[x]=y;
        }ll Ans=1;
        for(int i=1;i<=m;++i){
            int q=0;
            ans=0;
            for(int j=0;j<k[i];++j)if(~num[vec[i][j]])p[++q]=num[vec[i][j]];
            dfs(0,1,0,q,k[i],sum[i]);
            (Ans*=ans)%=mod;
        }
        cout<<Ans;
        return 0;
    }
  • 相关阅读:
    ASP.NET通用权限管理系统(FrameWork) 1.0.0 Release 发布
    ASP.NET通用权限管理系统(FrameWork) 1.0.3 Release
    ASP.NET通用权限管理系统(FrameWork) 之用户在线列表 泛型缓存 [原创]
    DDBuildToolsRelease1.0
    FineMessBox弹出窗口js (修改版,增加对Firefox支持)
    [开源]ASP.NET通用权限管理系统(FrameWork) 1.0.2 Release
    [开源]ASP.NET通用权限管理系统(FrameWork) 1.0.1 Release
    如何在CodePlex 创建开源项目
    今天上班遇到好人了
    ASP.NET通用权限管理系统(FrameWork) 在线演示地址
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10236873.html
Copyright © 2011-2022 走看看