题意:
给定1≤a,b,c≤2×105,现有0≤l≤3×105的长度向a,b,c添加,可以为0,可以最终有剩余
求新的a′,b′,c′形成不退化的三角形的方法数
分析:
首先,逆向思考,用总的−退化的三角形的方法数
total=C3l+3,如何理解呢,原来是将L长度分成4份,每份可以为0
现在是将L+4长度分成4份,每份至少为1,用隔板法即可得出结果(Ck−1n−1)
显然我们为求退化的方法数,要枚举最长边
令添加之后的边为a+x,b+y,c+z,x+y+z≤l,并假设a+x为最长边
那么a+x≥b+y+c+z⇒y+z≤a−b−c−x ...①
y+z≤l−x ...②
即y+z≤min(l−x,a−b−c−x)
令yz=y+z,那么y,z的取的方法数就是yz分成3份,每份可以为0,同理即为C2yz+2
代码:
//
// Created by TaoSama on 2016-02-04
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
typedef long long LL;
LL a[3], l;
LL gao(LL a, LL b, LL c, LL x) {
if(a + x < b + c) return 0;
LL yz = min(a - b - c + x, l - x);
return (yz + 2) * (yz + 1) / 2;
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> a[0] >> a[1] >> a[2] >> l) {
LL ans = (l + 3) * (l + 2) * (l + 1) / 6; //C(l+4-1,4-1);
//a+x>=b+y+c+z => y+z<=a-b-c+x
//x+y+z<=l => y+z<=l-x
//C(y+z+3-1,3-1)
for(int i = 0; i < 3; ++i)
for(LL x = 0; x <= l; ++x)
ans -= gao(a[i], a[(i + 1) % 3], a[(i + 2) % 3], x);
cout << ans << '\n';
}
return 0;
}