题意:给你三条边(x,y,z),你可以给三条边各自增加任意数值,但是增加的总和最多为(w)。求可以组成三角形的方案数。
分析:设(x y z)的增量为p1,p2,p3,假定(p1 + p2 + p3 = t,tin{[0, w]}),题目中要求的增量可以为0,如果按平常来说,对于形如(p1 + p2 + p3 = t,p1, p2, p3 > 0)的方程,这是不定方程的正整数根的方案个数,我们的求法是(隔板法),不定方程的正整数根的方案个数为(C_{t - 1}^{2}),然后如果不定方程的根是>=0的话,怎么办?我们可以做一个映射,(p1 + 1 + p2 + 1 + p3 + 1 = t + 3),令(q1 = p1 + 1, q2 = p2 + 1, q3 = p3 + 1),那么(q1 + q2 + q3 = t + 3),那么总的方案数为(sumlimits_{t = 0}^{t = w}C_{t + 2}^{2})。然后我们开始考虑不合法的方案,即(x + q1 >= y + q2 + z + q3)的方案数,我们可以得到(q1 >= y + z + q2 + q3 - x),因为(q1 + q2 + q3 = t),我们令(q2 + q3 = u,q1 = t - u),那么可以得到(t - u >= y + z - x + u),令(y + z - x = c),(c)是一个常数,(t - u >= c + u),那么可以得到(u <= frac{(t - c)}{2}),那么这种方案数有多少呢,即q2和q3的取法,我们依然可以使用隔板法,前面的球个数有p1个,后面有u = p2 + p3个,我们来分割u,可以发现有(frac{(u + 2) * (u + 1)}{2})种方案数,我们依次减掉x,y,z作为最长边的方案数即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
using LL = long long;
LL solve(int x, int y, int z, int t)
{
LL c = t - (y + z - x);
if (c < 0) return 0;
else
{
c = c / 2;
}
if (c > t) c = t;
return (LL)(c + 2) * (c + 1) / 2;
}
int main()
{
int x, y, z, w;
cin >> x >> y >> z >> w;
LL res = 0;
for (int i = 0; i <= w; ++i)
{
res += (LL)(i + 2) * (i + 1) / 2;
}
for (int i = 0; i <= w; ++i)
{
res -= solve(x, y, z, i);
res -= solve(y, x, z, i);
res -= solve(z, x, y, i);
}
cout << res << endl;
return 0;
}