CodeForces571A. Lengthening Sticks(组合数学-容斥)

题目大意:

a,b,c三根木棍能够增长三个不一样的数字,aa,bb,cc,且aa+bb+cc<=L,问能构成三角形的木棒有多少种方案c++

题目思路:

若是咱们直接考虑把L分配给aa,bb,cc好像很差下手ide

因此逆向考虑spa

合法的状况  =  全部状况 - 不合法的状况.net

 

step1:

首先计算全部的状况code

假设L当时为lblog

咱们把长度为l分配去的总的方案get

这个问题咱们等效为:有三个篮子,每一个篮子放至少一个个物品,总共l个物品,问有多少种方案class


咱们用插板法解决这个问题sed

由于每一个篮子放至少一个,而咱们的目标是能够放0个,怎么办呢?im

咱们能够增长几个物品使初始每一个篮子中就有一个,这里假设有m个篮子,n个物品

那咱们的物品个数变为n+m,这时候会产生n+m-1个隔板

而后咱们要选出m部分来,也就是放m-1个隔板

此时的方案为C(n+m-1,m-1)

 

回到这个题目

此时长度为l时,方案为C(l+3-1,3-1)

而后咱们枚举一遍l,求和算出总的方案

因此获得为l的时候方案为C(l+2,2)

step2:

求不合法的方案==

假设a+aa,b+bb,c+cc(aa,bb,cc分别为分配的增长的长度)

假设a+aa是那条最长的边

此时不合法须要知足以下条件:

b+bb+c+cc<=a+aa

bb+cc<=l-aa

bb+cc<=min(l-aa,a-b-c+aa)

令T=bb+cc

这个时候再进行一下问题转化

有T个物品,分配到三个篮子里(能够分配0个)

三个篮子分别是bb,cc和多余的部分

回到上面的插板法同样的解法C(t+3-1.3-1)

而后用总的减去不合法就ok了

 CODE:

ll b,c,a,l;
int main() {
    a=read(),b=read(),c=read(),l=read();
    ll zong = (l+1)*(l+2)*(l+3)/6ll;
    ll no;
    for(int aa=0 ; aa<=l ; aa++) {
        ll t = min(l-aa,a-b-c+aa);
        if(t<0) continue;
        no = (t+2)*(t+1)/2ll;
        zong-=no;
    }
    for(int bb=0 ; bb<=l ; bb++) {
        ll t = min(l-bb,b-a-c+bb);
        if(t<0) continue;
        no = (t+2)*(t+1)/2ll;
        zong-=no;
    }
    for(int cc=0 ; cc<=l ; cc++) {
        ll t = min(l-cc,c-b-a+cc);
        if(t<0) continue;
        no = (t+2)*(t+1)/2ll;
        zong-=no;
    }
    out(zong);
    return 0;
}
View Code
相关文章
相关标签/搜索