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.
The single line contains 4 integers a, b, c, l (1 ≤ a, b, c ≤ 3·105, 0 ≤ l ≤ 3·105).
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.
1 1 1 2
4
1 2 3 1
2
10 2 1 7
0
In the first sample test you can either not increase any stick or increase any two sticks by 1 centimeter.
In the second sample test you can increase either the first or the second stick by one centimeter. Note that the triangle made from the initial sticks is degenerate and thus, doesn't meet the conditions.
题意:给出a,b,c,L,要求a+x,b+y,c+z构成三角形,x+y+z<=L,问有多少中分法(x,y,z可为0)。
本来想写思路了,奈何岩兄写的太好了,我就不好意思写了,索性就用他的吧。
岩兄博客地址:点击打开链接
思路:用容斥来搞,结果ans=全部组合的情况-不符合三角形定理的情况。
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
……..
所以由上面可以推出当L=n时,全部的组合情况是C(2,2) + C(3,2) + ......C(l,2)。
2.不符合三角形定理的情况:
如果要形成一个三角形,那么必须任意两边之和大于第三边。那么不符合的就是任意一边大于等于其余两边的和。所以分别把a,b,c当成第三边,然后再考虑将剩下的l拆分三份分配给a,b,c依旧不满足的情况即可。
我们先把a当成第三边,然后给a增加一个La,现在i=a+La,Max=a+b+c+L。现在我们考虑b+c的范围,因为是不满足的情况,所以b+c的变化范围<=i,又因为总长度maxn的限制,b+c<=maxn-i,所以b+c的最大变化范围只能在min(i,maxn-i)。令x=min(i,maxn-i)-b-c表示总共变化量的大小,即Lb+Lc<=x,等价于tmp+Lb+Lc的方案数。
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
long long int minn(long long int xx,long long int yy){
if(xx<yy){
return xx;
}
return yy;
}
long long int IEP(long long int a,long long int b,long long int c,long long int l){
long long int s = 0;
long long int maxn = a + b + c + l;
for(long long int i=a;i<=a+l;i++){
if(b+c<=i){
long long int xx = min(i,maxn-i)-b-c;
s += (xx+1)*(xx+2)/2;
}
}
return s;
}
int main(){
__int64 a,b,c,l;
__int64 ans = 0;
while(scanf("%lld%lld%lld%lld",&a,&b,&c,&l)!=EOF){
ans = 0;
for(__int64 i=0;i<=l;i++){
ans += (i+1)*(i+2)/2;
}
ans -= IEP(a,b,c,l);
ans -= IEP(b,a,c,l);
ans -= IEP(c,a,b,l);
printf("%lld\n",ans);
}
return 0;
}