zoukankan      html  css  js  c++  java
  • CF451E Devu and Flowers (组合数学+容斥)

    题目大意:给你$n$个箱子,每个箱子里有$a_{i}$个花,你最多取$s$个花,求所有取花的方案,$n<=20$,$s<=1e14$,$a_{i}<=1e12$

    容斥入门题目

    把取花想象成往箱子里放花,不能超过箱子上限

    $n$很小,考虑状压

    如果去掉$a_{i}$的限制,我们取物品的方案数是$C_{s+n-1}^{n-1}$,可以想象成$s+n-1$个小球,我们取出$n-1$个隔板,分隔出来的其他$n$个部分就是每个箱子里花的数量

    但这样会算入不合法的方案,我们需要再去掉不合法的方案

    假设我们要满足i合法,那么首先分配给$i$,$ai+1$朵花,来保证它是不合法的

    然后,剩余$s+n-(ai+1)-1$朵花,我们仍然要分配给$n$个箱子,取出$n-1$个隔板,总方案数减去$C_{s+n-(ai+1)-1}^{n-1}$

    然而我们由算入了一些情况,即$i$不合法,$j$也不合法$(j!=i)$,在计算$i$和计算$j$时都去掉了这种情况,我们还要把它加回来

    总方案再加回来$C_{s+n-(ai+aj+2)-1}^{n-1}$

    然后又多减掉了$i,j,k$都不合法....依次容斥即可

    公式太长,也不好理解就不列了

    这道题的组合数很大,不能直接求,我们需要一些优化

    因为$n$很小,但$s$很大,所以上下化简掉阶乘里那一段特别长的部分,剩下的$O(n)$暴力计算就行了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define N 150
     5 #define uint unsigned int
     6 #define ll long long
     7 #define ull unsigned long long
     8 #define mod 1000000007
     9 using namespace std;
    10 //re
    11 /*int gint()
    12 {
    13     int ret=0,fh=1;char c=getchar();
    14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    16     return ret*fh;
    17 }*/
    18 int n;
    19 ll sum,ma;
    20 ll a[N],mu[N],inv[N],minv[N];
    21 ll qpow(ll x,ll y){
    22     ll ans=1;
    23     if(y){
    24         if(y&1) ans=ans*x%mod;
    25         x=x*x%mod,y>>=1;
    26     }return ans;
    27 }
    28 void Pre(){
    29     minv[0]=minv[1]=inv[0]=inv[1]=1;
    30     for(int i=2;i<=n;i++)
    31         inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod,minv[i]=minv[i-1]*inv[i]%mod;
    32 }
    33 ll C(ll a,ll b)
    34 {
    35     ll ans=1;
    36     if(b>a) return 0;
    37     if(b==0) return 1;
    38     for(ll j=a-b+1;j<=a;j++)
    39         ans=j%mod*ans%mod;
    40     ans=ans*minv[b]%mod;
    41     return ans;
    42 }
    43 ll Lucas(ll a,ll b)
    44 {
    45     if(b>a) return 0;
    46     if(a<mod&&b<mod) return C(a,b);
    47     else return Lucas(a%mod,b%mod)*Lucas(a/mod,b/mod)%mod;
    48 }
    49 
    50 int main()
    51 {
    52     //freopen("t1.in","r",stdin);
    53     scanf("%d%I64d",&n,&ma);
    54     int tot=(1<<n)-1;
    55     for(int i=0;i<n;i++)
    56         scanf("%I64d",&a[i]);
    57     ll ans=0;
    58     Pre();
    59     for(int s=0;s<=tot;s++)
    60     {
    61         ll res=ma;int cnt=0;
    62         for(int i=0;i<n;i++)
    63             if(s&(1<<i)) res-=a[i]+1,cnt++; 
    64         if(res<0) continue;
    65         (ans+=1ll*(cnt&1?-1:1)*Lucas(res+n-1,n-1)%mod+mod)%=mod;
    66     }
    67     printf("%I64d
    ",ans);
    68     return 0;
    69 }
  • 相关阅读:
    Android weight属性详解
    设计模式(一)__单例设计模式
    Java中线程的生命周期
    抽象类和接口
    SQL sever 怎样将DBF文件导入到数据库
    JS去除字符串中空格,及常用正则表达式
    Oracle 11g问题1:关于error:ORA12541: TNS: 没有监听器
    access、excel取随机n条记录
    tsql字符串操作
    测试SQL Server执行时间和CPU时间
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9885375.html
Copyright © 2011-2022 走看看