• bzoj 4710 : [Jsoi2011]分特产


      好久没做组合的题竟然懵逼了好长时间,去吃了顿饭就突然会做了。。。

      如果没有每个人至少一个的限制的话那么答案显然是∏(c(n-1,a[i]+n-1)),相当于把每一种物品排成一排然后每排放(n-1)个隔板,第i个隔板和第i+1个隔板之间的物品就是第i个人的物品,显然每种方案对应着一种实际方案(会组合的人就当我是在废话吧)。

      那么如果加上限制呢,第一反应显然是容斥,上一段算出的答案可能有一个人没有,那就减去n-1个人的所有合法方案(没有空的人)*n(枚举谁没有),如果有两个人没有那就减去n-2个人的合法方案*c(n,2),这东西显然可以递推,那就做完了。

      

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define ll long long
     6 #define N 2005
     7 using namespace std;
     8 int read()
     9 {
    10     int p=0;char c=getchar();
    11     while(c<'0'||c>'9')c=getchar();
    12     while(c>='0'&&c<='9')p=p*10+c-'0',c=getchar();
    13     return p;
    14 }
    15 const int p = 1000000007;
    16 int c[N][N];
    17 void yu()
    18 {
    19     for(int i=0;i<=2000;i++)
    20     {
    21         c[i][0]=1;
    22         for(int j=1;j<=i;j++)
    23         {
    24             c[i][j]=(c[i-1][j-1]+c[i-1][j])%p;
    25         }
    26     }
    27     return ;
    28 }
    29 int n,m;
    30 int a[N];
    31 int f[N];
    32 int main()
    33 {
    34     scanf("%d%d",&n,&m);
    35     yu();
    36     for(int i=1;i<=m;i++)scanf("%d",&a[i]);
    37     for(int i=1;i<=n;i++)
    38     {
    39         f[i]=1;
    40         for(int j=1;j<=m;j++)
    41         {
    42             f[i]=((ll)f[i]*c[a[j]+i-1][i-1])%p;;
    43         }
    44         for(int j=1;j<i;j++)
    45         {
    46             f[i]=(f[i]-((ll)f[j]*c[i][i-j])%p+p)%p;
    47         }
    48     }
    49     printf("%d
    ",f[n]);
    50     return 0;
    51 }
  • 相关阅读:
    php 替换二维数组的 key
    全选功能
    向数组中添加含有下标的元素
    判断一个进程是否在执行中
    初识 Nginx
    原生JS中DOM节点相关API合集
    工作中经常用到github上优秀、实用、轻量级、无依赖的插件和库
    Unsupported major.minor version ... JDK具体对应版本
    Scala常用命令
    使用nexus搭建maven私服教程详解
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6446119.html
Copyright © 2020-2023  润新知