【jzoj4965】【Equation】【容斥】

来源:互联网 发布:java接口上传文件 编辑:程序博客网 时间:2024/05/07 10:42

题目大意

听着自己美妙的曲子,小Z进入了梦乡。在梦中,小Z仿佛又回到了自己纵横考场的年代。在梦中,小Z参加了一场考试,这场考试一共有n道题,每道题的最终得分都是一个大于等于0的整数。然而醒来后,小Z忘记了自己每道题的得分。他只记得自己计算过m次一些题目的分数和,每道题都被计算过,并且只被计算过一次。除此之外他还记得其中t道题的满分分别是多少(一道题的得分不会超过满分)。现在小Z想知道他这场考试有多少种得分情况(至少有一道题的得分不同就算不同的情况),因为这个答案可能很大,你只需要输出答案对1,000,000,007取模后的结果即可。

解题思路

考虑没有限制的情况,可以用隔板原理求出。考虑到限制很少可以用容斥原理,强制分配使其非法,用隔板原理求出,对于没限制的情况可以提前求出。

code

#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define LF double#define LL long long#define min(a,b) ((a<b)?a:b)#define max(a,b) ((a>b)?a:b)#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const mxn=1e6,mo=1e9+7;int n,m,t,ans,cnt,preans=1,tag[mxn+10],a[mxn+10][2],b[30][2],d[30][2],renum[mxn+10],bel[mxn+10],fact[mxn*2+10],ni[mxn*2+10];int c(int x,int y){    return 1ll*fact[x]*ni[y]%mo*ni[x-y]%mo;}void dfs(int now,int tag){    if(now>t){        int tmp=1;        fo(i,1,cnt)            tmp=1ll*tmp*((d[i][1]>=0)?(c(d[i][1]+d[i][0]-1,d[i][0]-1)):0)%mo;        ans=(ans+1ll*tag*preans*tmp%mo)%mo;        return;    }    d[bel[b[now][0]]][1]-=b[now][1]+1;    dfs(now+1,-tag);    d[bel[b[now][0]]][1]+=b[now][1]+1;    dfs(now+1,tag);}int Pow(int x,int y){    int z=1;    while(y){        if(y&1)z=1ll*z*x%mo;        x=1ll*x*x%mo;        y=y>>1;    }    return z;}int read(){    int v=0;char ch=getchar();    for(;(ch<'0')||(ch>'9');ch=getchar());    for(;(ch>='0')&&(ch<='9');v=v*10+ch-'0',ch=getchar());    return v;}int main(){    //freopen("equation.in","r",stdin);    //freopen("equation.out","w",stdout);    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    n=read();m=read();int x;    fact[0]=ni[0]=1;fo(i,1,mxn*2)fact[i]=1ll*fact[i-1]*i%mo,ni[i]=Pow(fact[i],mo-2);    fo(i,1,m){        a[i][0]=read();        fo(j,1,a[i][0])x=read(),bel[x]=i;        a[i][1]=read();    }    t=read();    fo(i,1,t)b[i][0]=read(),b[i][1]=read(),tag[bel[b[i][0]]]=1;    fo(i,1,m)if(tag[i])cnt++,d[cnt][0]=a[i][0],d[cnt][1]=a[i][1],renum[i]=cnt;    else preans=1ll*preans*c(a[i][0]+a[i][1]-1,a[i][0]-1)%mo;    fo(i,1,t)bel[b[i][0]]=renum[bel[b[i][0]]];    dfs(1,1);    printf("%d",(ans%mo+mo)%mo);    return 0;}
0 0
原创粉丝点击