CF 317 A. 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.
The single line contains 4 integers a, b, c, l (1 ≤ a, b, c ≤ 3·10^5, 0 ≤ l ≤ 3·10^5).
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。可以把长度 len(len<= L)拆成三份后,添加到a,,b,c任意一边。问能构成的三角形的个数。(a=2,b=2,c=3 和 a=3,b=2,c=2是两种不同的情况)
比如说样例2,1 2 3 1。可以把1加到a上 变成2 2 3,可以把1加到b上 变成1 3 3。所以答案输出2。
思路:
全部情况 - 不构成三角形的情况 = 构成三角形的情况
全部情况:
对于长度len,考虑切2刀分成3部分,因为可以是切在0这个位置上,即可以出现0,0,len这种情况,所以情况一共有C(len+2,2),表示把长度为len的线段,取2个点切开,然后把这三段分配给a,b,c的所有情况。(包括可构成三角形和不可构成三角形)
不构成三角形的情况:
一个三角形三边分别为a,b,c,如果a>=b+c,则构不成三角形。
首先考虑最长边是a,对于要加的len,分成p和len-p两部分,其中p给a,len-p给b和c。可以确定的是如果a>=b+c,那么p最少可以是0,如果b+c>a,那么p起码得是b+c-a。这样才能满足即使len-p是0的情况下,让a+p>=b+c。
所以枚举p的起点是max(b+c-a,0)。之后考虑len-p分配给b和c的情况有几种。
因为要构成a+p>=b+c+len-p。所以最大可增加的长度是min(len-p,a+p-b-c),(解释一下,len-p是给了a之后剩下来的,a+p-(b+c)是本身要满足a+p>=b+c,最多允许a+p==b+c,所以对这两个值取最小值就是b和c最大可以增加的长度)
记这个最大可以增加的长度为max_addlen,分配给b和c的情况一共有 (max_addlen+1)*(max_addlen+2)/2 种。
这个很容易证明,在max_len中间砍两刀分为3部分,其中2部分给b和c。情况依旧是C(max_addlen+2,2)
所以去枚举增加长度就可以得到构不成三角形的全部情况了。具体看代码,同时注意用long long。
代码:
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define MM(x) memset(x,0,sizeof(x)) #define MMINF(x) memset(x,INF,sizeof(x)) #define LL long long using namespace std; LL l; LL solve(LL a,LL b,LL c)//枚举a为最长边时候所有构不成三角形的情况 { LL ans = 0; for(LL i = max(b+c-a,0LL) ; i <= l ; i ++) //起点是max(b+c-a,0LL) { LL max_addlen = min(a+i-b-c,l-i);//给b和c 最大可以增加的长度 ans += (max_addlen+1)*(max_addlen+2)/2; } return ans; } int main() { LL a,b,c ; cin>>a>>b>>c>>l; LL ans = 0; for(LL i = 0 ; i <= l ; i ++){ ans += (i+1)*(i+2)/2; }//可增加的所有情况 ans -= solve(a,b,c); ans -= solve(b,a,c); ans -= solve(c,a,b); //分别枚举a,b,c是最长边的情况 cout<<ans<<endl; } /* 10 2 1 7 1 2 3 1 */