CodeForces571A. Lengthening Sticks(組合數學-容斥)

UpMing發表於2021-04-04

題目大意:

a,b,c三根木棍可以增加三個不同的數字,aa,bb,cc,且aa+bb+cc<=L,問能構成三角形的木棒有多少種方案

題目思路:

如果我們直接考慮把L分配給aa,bb,cc好像不好下手

所以逆向考慮

合法的情況  =  所有情況 - 不合法的情況

 

step1:

首先計算所有的情況

假設L當時為l

我們把長度為l分配去的總的方案

這個問題我們等效為:有三個籃子,每個籃子放至少一個個物品,總共l個物品,問有多少種方案


我們用插板法解決這個問題

因為每個籃子放至少一個,而我們的目標是可以放0個,怎麼辦呢?

我們可以增加幾個物品使初始每個籃子中就有一個,這裡假設有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:

CodeForces571A. Lengthening Sticks(組合數學-容斥)
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

 

相關文章