1. 程式人生 > >CodeForces - 572C——思維

CodeForces - 572C——思維

題意:給定三個木棍,長度為a b c,現在可以給任意木棍增加任意長度(整數),但是增加的長度總數不能超過l(3e5),問有多少種增加方式使得增加完長度後的三個木棍可以構成一個三角形

思路:剛開始想到列舉一個最長的木棍,然後列舉該木棍增加的長度,然後計算另外兩個木棍的合法情況數,但是不是很好計算,因為合法即要考慮兩邊之和大於第三邊,有要考慮另外兩個木棍增加長度後不能超過當前列舉的木棍的長度(因為我們一開始假設這根木棍最長),但是反著想就比較好像,我們首先算一下所有分配情況,然後按照上述的方法列舉,減去非法情況,對於非法情況我們只要考慮兩邊之和小於等於第三邊即可,因為兩邊之和小於第三邊了兩邊的長度一定都小於第三邊,不會破壞當前列舉的木棍是最長的這個假設。

中間的計算都是經典的組合數問題,想一下就好了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a, b, c, l;
ll cal(int x) {
    return 1LL*(x+2)*(x+1)/2;
}
ll cal_(int x, int y, int z) {
    ll ans = 0;
    for (int i = 0; i <= l; i++) {
        if (x + i < y + z) continue;
        int t = min(x + i - y - z, l - i);
        ans += 1LL*(t+2)*(t+1)/2;
    }
    return ans;
}
int main() {
    scanf("%d %d %d %d", &a, &b, &c, &l);
    ll ans = 0;
    for (int i = 0; i <= l; i++) {
        ans += cal(i);
    }
    ans -= cal_(a, b, c);
    ans -= cal_(b, a, c);
    ans -= cal_(c, a, b);
    printf("%lld\n", ans);
    return 0;
}