51Nod-1509-加长棒

来源:互联网 发布:数据分析师有前景嘛 编辑:程序博客网 时间:2024/04/30 07:21

ACM模版

描述

描述

题解

今天做了两个题,都有些懵,这道题一开始想着要dp,可是,屡试不通……

还是老办法,找题解喽,毕竟思而不学则殆,是需要学习一下这种题型的解题思路了。

看到一篇题解,看得不是完全懂,大体的算法思路懂了,可是推导的过程有些懵逼……

题解如下(题解来自ITAK大牛的博客):

这个题目直接想的话没法做,所以就是间接的想,也就是采用容斥原理从反面来想,
也就是说用总数减去不能够满足三角形的方法数,那么先来求总数,
因为现在的问题是将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>using namespace std;typedef long long ll;ll Solve(ll a, ll b, ll c, ll L)    //  a是三边之间最大的{    ll tmp = a + b + c + L;    ll ans = 0;    for (ll i = 0; i <= L; i++)    {        ll tmp_ = min(tmp - a - i, i + a);        if (b + c <= tmp_)        {            ans += (tmp_ - b - c + 2) * (tmp_ - b - c + 1) / 2;        }    }    return ans;}int main(){    ll a, b, c, L;    while (cin >> a >> b >> c >> L)    {        //  挡板法求所有可能数        ll ans = (L + 3) * (L + 2) * (L + 1) / 6;        ans -= Solve(a, b, c, L);        ans -= Solve(b, a, c, L);        ans -= Solve(c, a, b, L);        cout<< ans <<endl;    }    return 0;}
0 0
原创粉丝点击