组合数学 —— 基本计数原理

【抽屉原理】

1.内容

把 n+1 件东西放入 n 个抽屉,则至少有一个抽屉里放两件或两件以上的东西。

从令一角度说,把 n-1 件东西放入 n  个抽屉,则至少一个抽屉是空的。

2.经典应用

给出一个含有 n 个数字的序列,要找一个连续的子序列,使他们的和一定是 c 的倍数

假设 sum[i] 存储整数序列中的前 i 项和

根据抽屉原理,以 sum 数组构造抽屉 drawer 数组,其保存的是最先出现的 sum[i] 的下标,当 sum 的一个元素第二次放入重复的抽屉时,输出结果。

若 sum[i] 是 c 的倍数,直接输出前 i 项即可,若 sum[i] 不是 c 的倍数,则需要计算 sum[i]%c,此时,sum[i]%c = sum[j]%c,i!=j 肯定存在,即第 j 到第 i 项数的和为 c 的倍数。

LL a[N],drawer[N];
LL sum[N];
int main(){
    LL c,n;
    while(scanf("%lld%lld",&c,&n)!=EOF&&c&&n){
        memset(drawer,-1,sizeof(drawer));
        drawer[0]=0;
        sum[0]=0;
        
        for(LL i=1;i<=n;i++){//计算前缀和
            scanf("%lld",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        
        for(LL i=1;i<=n;i++){
            if(drawer[sum[i]%c]!=-1){
                for(LL j=drawer[sum[i]%c]+1;j

【加法原理与乘法原理】

1.分类加法原理

做一件事,完成它有 n 类方式,第一类方式有 M1 种方法,第二类方式有 M2 种方法,…,第 n 类方式有 Mn 种方法,那么完成这件事共有 M1+M2+……+Mn 种方法。

例如:从北京到上海有火车、飞机、轮船 3 种方式,火车、飞机、轮船分别有 k1,k2,k3 个班次,那么从北京到上海有 k1+k2+k3 种方式可以到达。

2.分步乘法原理

做一件事,完成它要分成 n 个步骤,第一步有 M1 种不同的方法,第二步有 M2 种不同的方法,…,第 n 步有 Mn 种不同的方法,那么完成这件事共有 M1×M2×M3×…×Mn 种不同的方法。

例如:从北京乘坐火车到上海,需要转 3 次车,每次专车分别有 k1,k2,k3 个班次,那么从北京到上海有 k1×k2×k3 种方式可以到达。

3.联系

分类加法原理和分步乘法原理是两个基本原理,回答的都是有关做一件事的不同方法种数的问题。

两者区别在于:分类计数原理针对的是分类问题,其中各种方法相互独立,用任何一种方法都可以完成这件事;分步计数原理针对的是分步问题,各步骤中的方法相互依存,只有各个步骤都完成才算完成事情。

分类要依据同一标准划分,既必须包括所有情况,又不要交错在一起产生重复;分步则应使各步依次完成,保证整个事件得到完成,既不得多余重复,也不缺少某一步骤。

【应用】

根据研究对象的有无,一般将组合数学分为排列问题和组合问题。

其根本不同是排列问题与元素顺序有关,组合问题与元素顺序无关。

在排列与组合问题中,经常会出现计数问题,解决计数问题的思路一般有以下三种:

1)只取需要的。将各种符合条件的情形枚举出来,再利用加法原理求和。

2)先取后排。将各步符合条件的排列或组合计算出来,再根据乘法原理求积。

3)先全部取,再减去不要的。利用容斥定理,将各种符合条件的情形枚举出来,再减去不符合条件的。

关于容斥定理:点击这里

【例题】

  1. 吃糖果(HDU-1205)(抽屉原理):点击这里
  2. Find a multiple(POJ-2356)(抽屉原理):点击这里
  3. Halloween treats(HDU-1808)(抽屉原理):点击这里
  4. Polycarp's Pockets(CF-1003A)(抽屉原理):点击这里
  5. Lining Up(AtCoder-2271)(分步乘法原理):点击这里

你可能感兴趣的:(—————组合数学—————,#,组合数学——基本计数原理)