zoukankan      html  css  js  c++  java
  • [JSOI 2011]分特产

    Description

    JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们。
    JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望任何一个同学因为没有拿到特产而感到失落,所以每个同学都必须至少分得一个特产。
    例如,JYY 带来了2 袋麻花和1 袋包子,分给A 和B 两位同学,那么共有4 种不同的分配方法:
    A:麻花,B:麻花、包子
    A:麻花、麻花,B:包子
    A:包子,B:麻花、麻花
    A:麻花、包子,B:麻花

    Input

    输入数据第一行是同学的数量N 和特产的数量M。
    第二行包含M 个整数,表示每一种特产的数量。
    N, M 不超过1000,每一种特产的数量不超过1000

    Output

    输出一行,不同分配方案的总数。由于输出结果可能非常巨大,你只需要输出最终结果MOD 1,000,000,007 的数值就可以了。

    Sample Input

    5 4
    1 3 3 5

    Sample Output

    384835

    题解

    想到了隔板法,想到了容斥...就是不知道怎么写...

    对于总共$n$个人,很容易想到第$i$个物品,分出的方案数为$C^{n-1} _{a[i]+n-1}$,其中$a[i]$为个数(隔板法)。

    但是这样做就会导致有人分不到特产。

    考虑容斥,我们-一个人分不到的情况+两个人分不到的情况-三个人...

    我们直接限定隔板的数目来强制一些人分不到特产,即方案数变为$C^{n-1-i} _{a[j]+n-1-i}$,其中$i$个人强制分不到,第$j$个物品。

    注意最后,因为分不到的人可以是任意的,所以每次容斥还要*$C^i _n$。

     1 //It is made by Awson on 2017.9.25
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime> 
     6 #include <queue>
     7 #include <stack>
     8 #include <string>
     9 #include <cstdio>
    10 #include <vector>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define Min(a, b) ((a) < (b) ? (a) : (b))
    16 #define Max(a, b) ((a) > (b) ? (a) : (b))
    17 #define LL long long
    18 using namespace std;
    19 const int N = 1000;
    20 const int MOD = 1000000007;
    21 
    22 int n, m, mx;
    23 int a[N+5];
    24 int C[N*2+5][N*2+5];
    25 
    26 void work() {
    27     scanf("%d%d", &n, &m);
    28     for (int i = 1; i <= m; i++) {
    29         scanf("%d", &a[i]);
    30         mx = Max(mx, a[i]);
    31     }
    32     mx += n;
    33     for (int i = 0; i <= mx; i++) {
    34         C[i][0] = 1;
    35         for (int j = 1; j <= i; j++)
    36             C[i][j] = (C[i-1][j-1]+C[i-1][j])%MOD;
    37     }
    38     LL ans = 0;
    39     for (int i = 0; i < n; i++) {
    40         LL cnt = 1;
    41         for (int j = 1; j <= m; j++)
    42             cnt = cnt*C[a[j]+n-1-i][n-1-i]%MOD;
    43         cnt = cnt*C[n][i]%MOD;
    44         if (i%2) ans = (ans+MOD-cnt)%MOD;
    45         else ans = (ans+cnt)%MOD;
    46     }
    47     printf("%lld
    ", ans);
    48 }
    49 int main() {
    50     work();
    51     return 0;
    52 }
  • 相关阅读:
    获取html页面传递过来的参数
    jqueryWeiui+pagehelper滚动加载(实现分页)
    【JS】js随笔
    【Java】Java基础
    【FrameWork】Hibernate
    【FrameWork】Struts2
    去掉inline-block间的间隙
    javascript单例模式
    关于call/apply与bind的一点误解
    git笔记-常用命令
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7594023.html
Copyright © 2011-2022 走看看