现在有三根木棒,他们的长度分别是a,b,c厘米。你可以对他们进行加长(不同的木棒可以增加不同的长度),他们总的加长长度不能超过L厘米。你也可以不对他们进行加长。
现在请你计算一下有多少种加长的方式使得他们能构成合法的三角形(面积非0)。
单组测试数据。 共一行,包含4 个整数a,b,c,L (1≤a,b,c≤3*10^5, 0≤L≤3*10^5)。
输出答案占一行。
1 1 1 2
4
解题思路:
这个题目直接想的话 没法做,所以就是间接的想,也就是采用容斥原理从反面来想,也就是说 用总数减去不能够满足三角形的方法数,那么先来
求总数,因为现在的问题是将 L 分成四份, 一份给 a 一份给 b 一份给 c 剩下的就是剩下的了,那么分成的四份可能有 0 , 不满足
挡板法的条件,所以我们就将 L+4 ,那么现在在分成四份就符合条件啦,所以总的方法数就是 C(L+4−1,4−1) , 那么现在再来求不满足
三角形条件的方法数,因为三角形一定满足一个条件是 两边之和大于第三边 所以我们只要求出 两条较小的边小于等于最大边就不满足条件了,
然后根据这个可以列一个方程,假设 a 现在加上了 x , b 现在加上了 y , c 现在加上了 z (假设 a 是最大边),方程如下:
b+y+c+z≤a+x
然后因为所有数的和一定是 a+b+c+L ,所以最大值不可能超过 a+b+c+L ,那么 b+c≤a+b+c+L−(a+x) 综上 所以有 b+c≤min(a+b+c+L−a,a+x)
然后在利用挡板法求出 不能组成三角形的方法数,是 C(min−b−c+2,2) 所以就可以写了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <stack>
#define maxn 1000005
#define INF 1000000009
typedef long long ll;
using namespace std;
ll solve(ll a, ll b, ll c, ll m){
ll k = 0;
for(ll i = 0; i <= m; i++){
ll temp = min(m+a+b+c-a-i, a+i);
if(temp < b + c)
continue;
temp -= b + c;
k += (temp+2) * (temp+1) / 2;
}
return k;
}
int main(){
ll a, b, c, m;
scanf("%I64d%I64d%I64d%I64d", &a, &b, &c, &m);
ll ans = (m+3) * (m+2) * (m+1) / 6;
ans -= solve(a, b, c, m);
ans -= solve(b, a, c, m);
ans -= solve(c, a, b, m);
cout << ans << endl;
return 0;
}