其他分享
首页 > 其他分享> > 【Codeforces Round #643 (Div. 2) C】Count Triangles

【Codeforces Round #643 (Div. 2) C】Count Triangles

作者:互联网

题目链接

链接

翻译

让你找 \(3\) 条边 \(x,y,z\), 要求 \(A\le x\le B\le y\le C\le z\le D\)

且 \(x,y,z\) 能组成三角形。

问你这样的 \(x,y,z\) 的个数。

题解

对于最后选出来的边,我们只需要关注 \(x+y\) 是不是大于 \(z\) 就好了 (两边之和大于第三边)。

因为 \(x<=y<=z\) 且 \(x,y,z\) 都是正整数。所以 \(y+z>x\) 和 \(z+x>y\) 恒成立。

首先, 比较明显的是我们可以先枚举其中一条边 \(x\) 。

然后 \(y\) 的话会从 \(B\) 到 \(C\) 变化,那么 \(x+y\) 就会在 \([x+B,x+C]\) 这个区间内变化。

这个区间和 \([C,D]\) 这个区间的相交情况有 \(5\) 种可能(除去完全在 \([C,D]\) 左边这种情况不可能)。

分别把这 \(5\) 种情况画出来, 算一下 \(y\) 在这个区域里面对答案的贡献就好了(\(z\) 的值要比 \(x+y\) 来的小)。

会对应很多的类似1,2,3,4... 的公差为 \(1\) 的等差数列(用求和公式算一下答案)。以及整个 \([C,D]\) 区域的值都可以取的情况(x+y>D)。

强烈建议画个数轴来讨论!

代码

#include <bits/stdc++.h>
#define LL long long
using namespace std;

LL a,b,c,d;

int main(){
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> a >> b >> c >> d;
    LL ans = 0;
    for (LL x = a;x <= b;x++){
        if (x+b>d){
            ans += (d-c+1)*(c-b+1);
            continue;
        }
        if (x+b <= c && x+c <= d){
            ans += (1+x)*x/2;
        }
        if (x+b <= c && x+c > d){
            ans += (1+d-c)*(d-c)/2+(x+c-d)*(d-c+1);
        }
        if (x+b > c && x+c <= d){
            LL a1 = x+b-c,n = c-b+1;
            LL an = a1 + n - 1;
            ans += (a1+an)*n/2;
        }
        if (x+b > c && x+c > d){
            LL a1 = x + b - c;
            LL n = (d-x-b+1);
            LL an = a1 + n-1;
            ans += (a1+an)*n/2;
            ans += (x+c-d)*(d-c+1);
        }
    }
    cout << ans << endl;
    return 0;
}

标签:Count,le,LL,Codeforces,long,a1,643,&&,ans
来源: https://www.cnblogs.com/AWCXV/p/14093130.html