2928. 给小朋友们分糖果 II ——O(1)数学公式

计算合法分配方案数的方法:

合法方案数(所有小朋友糖果数 ≤ limit) = 总方案数 - 非法方案数(至少一个小朋友糖果数 > limit)

  1. 总方案数(不考虑limit限制): 将n个小球分配给3个不同盒子 相当于在n+2个位置中选择2个位置放置隔板 公式:C(n+2, 2)

  2. 非法方案数(至少一个小朋友糖果数 > limit): 采用容斥原理计算:

    • 单个小朋友超过limit的情况(集合A,B,C): 已分配(limit+1)个糖果,剩余n-(limit+1)个 每种情况方案数:C(n-(limit+1)+2, 2)

    • 两个小朋友同时超过limit的情况(集合A∩B,B∩C,C∩A): 已分配2*(limit+1)个糖果,剩余n-2*(limit+1)个 每种情况方案数:C(n-2*(limit+1)+2, 2)

    • 三个小朋友同时超过limit的情况(集合A∩B∩C): 已分配3*(limit+1)个糖果,剩余n-3*(limit+1)个 方案数:C(n-3*(limit+1)+2, 2)

最终计算公式: C(n+2,2) - 3C(n-(limit+1)+2,2) + 3C(n-2*(limit+1)+2,2) - C(n-3*(limit+1)+2,2)

class Solution {
public:
    /*
    合法方案数(所有小朋友分到的糖果数 < = limit) = 不考虑limit的所有方案数 - 不合法方案数(至少有一个小朋友分到的糖果数  > limit) 
    不考虑limit的所有方案数:
    n个小球放到3个有区别的盒子中
    n + 2 个位置,2个放隔板,剩下n个放小球
    C(n + 2,2)
    不合法方案数(至少有一个小朋友分到的糖果数  > limit)
    集合A:甲分到的糖果数 > limit(乙丙分到的不管) 已经分出去了limit + 1 剩下n - limit - 1分给3个小朋友
    集合B:乙分到的糖果数 > limit(甲丙分到的不管)
    集合C:丙分到的糖果数 > limit(甲乙分到的不管)
    集合A∩B:甲乙分到的糖果数 > limit(丙分到的不管) 已经分出去了2*(limit + 1) 剩下n - 2*(limit + 1)分给3个小朋友
    集合B∩C:乙丙分到的糖果数 > limit(甲分到的不管)
    集合C∩A:甲丙分到的糖果数 > limit(乙分到的不管)
    集合A∩B∩C:甲乙丙分到的糖果数 > limit  已经分出去了3*(limit + 1) 剩下n - 3*(limit + 1)分给3个小朋友
    A + B + C - A∩B - B∩C - A∩C + (A∩B∩C)
    C(n + 2,2) - 3 * C(n - limit - 1 + 2,2) + 3 * C(n - 2*limit - 2 + 2,2) - C(n - 3*(limit + 1) + 2,2)
    */
    int distributeCandies(int n, int limit) {
       auto c2 = [&](this auto && c2,int n)->int{
            if (n > 1) {
                return n * (n - 1) / 2;
            }
            return 0;
       }; 
       return c2(n + 2) - 3 * c2(n - limit - 1 + 2) + 3 * c2(n - 2*limit - 2 + 2) - c2(n - 3*(limit + 1) + 2);
    }
};

        时间复杂度:O(1)

        空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值