Lengthening Sticks 组合数+容斥原理

You are given three sticks with positive integer lengths of a, b, and c centimeters. You can increase length of some of them by some positive integer number of centimeters (different sticks can be increased by a different length), but in total by at most l centimeters. In particular, it is allowed not to increase the length of any stick.

Determine the number of ways to increase the lengths of some sticks so that you can form from them a non-degenerate (that is, having a positive area) triangle. Two ways are considered different, if the length of some stick is increased by different number of centimeters in them.

Input
The single line contains 4 integers a, b, c, l (1 ≤ a, b, c ≤ 3·105, 0 ≤ l ≤ 3·105).

Output
Print a single integer — the number of ways to increase the sizes of the sticks by the total of at most l centimeters, so that you can make a non-degenerate triangle from it.

Example
Input
1 1 1 2
Output
4
Input
1 2 3 1
Output
2
Input
10 2 1 7
Output

0

思路:用容斥来搞,结果ans=全部组合的情况-不符合三角形定理的情况。

题意:给出a,b,c,L,要求a+x,b+y,c+z构成三角形,x+y+z<=L,问有多少中分法(x,y,z可为0)。

当x+y+z =Li时,若x>=0,y>=0,z>=0,假设dx=x+1,dy=y+1,dz=z+1,则dx+dy+dz=Li+3;

利用插板法,Li+3个球分成三份,Li+2个空插两个板子,有C(Li+2,2)种情况

1.全部组合的情况: 
当L=0时,res=1; 
当L=1时,res=3;所以当L=1时形成的情况为1+3=4 
当L=2时,res=6;所以当L=2时形成的情况为4+6=10 
当L=3时,res=10; 所以当L=3时形成的情况为10+10=20 
…….. ,

C(m-1,n-1)+C(m-1,n)=C(m,n)

所以由上面可以推出当L=n时,全部的组合情况是C(n+3,3)。 
2.不符合三角形定理的情况: 
如果要形成一个三角形,那么必须任意两边之和大于第三边。那么不符合的就是任意一边大于等于其余两边的和。所以分别把a,b,c当成第三边,然后再考虑将剩下的l拆分三份分配给a,b,c依旧不满足的情况即可。 
我们先把a当成第三边,然后给a增加一个La,现在i=a+La,Max=a+b+c+L。现在我们考虑b+c的范围,因为是不满足的情况,所以b+c的变化范围<=i,又因为总长度Max的限制,b+c<=Max-i,所以b+c的最大变化范围只能在min(i,Max-i)。令x=min(i,Max-i)-b-c表示总共变化量的大小,即Lb+Lc<=x,等价于tmp+Lb+Lc的方案数。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;

ll ex(ll a ,ll b,ll c,ll k)
{
    ll ans=0;
    ll maxx=a+b+c+k;
    for(ll i=a;i<=a+k;i++)
    {
        if(b+c>i)  continue;
        else
        {
            ll x=min(i,maxx-i)-b- c;
            ans+=(x+2)*(x+1)/2;
        }
    }
    return ans;
}

int main()
{
    ll a,b,c,k,ans;
    while(~scanf("%lld%lld%lld%lld",&a,&b,&c,&k))
    {
        ans=(k+3)*(k+2)*(k+1)/6;
        ans-=ex(a,b,c,k);
        ans-=ex(b,a,c,k);
        ans-=ex(c,b,a,k);
        printf("%lld\n",ans);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值