Lengthening Sticks 组合数+容斥原理

来源:互联网 发布:蓝牙串口软件ymodem 编辑:程序博客网 时间:2024/05/17 06:26
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);    }}

阅读全文
0 0
原创粉丝点击