• bzoj 4710


    非常简单的组合数学+容斥原理

    直接计算不好计算,我们用容斥原理计算:所有人随便选-至少有一个人没有礼物+至少有两个人没有礼物...

    假设我们有$i$个人没有礼物,那么方案数为$C_{n}^{i}prod_{j=1}^{m}C_{a[j]+n-i-1}^{n-i-1}$

    后面那个组合数的含义是对于每一种特产,这种特产共有$a[j]$个,将其分给$n-i$个人,允许有人拿不到的方案数

    可以理解成共有$a[j]+n-i-1$个位置,在其中插入$n-i-1$个隔板的方案数

    因此总答案即为$sum_{i=0}^{n}(-1)^{i}C_{n}^{i}prod_{j=1}^{m}C_{a[j]+n-i-1}^{n-i-1}$

    贴代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    const ll mode=1000000007;
    ll n,m;
    ll mul[1000005];
    ll inv[1000005];
    ll minv[1000005];
    ll a[1000005];
    void init()
    {
        inv[0]=inv[1]=minv[0]=minv[1]=mul[0]=mul[1]=1;
        for(int i=2;i<=1000000;i++)
        {
            inv[i]=(mode-mode/i)*inv[mode%i]%mode;
            mul[i]=mul[i-1]*i%mode;
            minv[i]=minv[i-1]*inv[i]%mode;
        }
    }
    ll C(ll x,ll y)
    {
        if(x<=y)return 0;
        return mul[x]*minv[y]%mode*minv[x-y]%mode;
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        init();
        for(int i=1;i<=m;i++)scanf("%lld",&a[i]);
        ll ans=0,f=1;
        for(int i=0;i<=n;i++)
        {
            ll sum=1;
            for(int j=1;j<=m;j++)sum=(sum*C(a[j]+n-i-1,n-i-1))%mode;
            ans=((ans+f*C(n,i)%mode*sum%mode)%mode+mode)%mode;
            f=-f;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    处理流之转换流
    处理流之缓冲流 buffered
    java学习笔记 字符流Reader与Writer
    java学习笔记 OutputStream与InputStream
    java学习笔记 Map接口
    java 学习笔记 Iterator 迭代器
    java学习笔记 genenic 范形
    应急响应介绍
    安全之红蓝对抗简介
    密码学基础下篇
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10969784.html
Copyright © 2020-2023  润新知