C. Count Triangles
题目链接-C. Count Triangles
题目大意
给你四个数
A
,
B
,
C
,
D
A,B,C,D
A,B,C,D,求有多少个三边为
x
,
y
,
z
(
A
≤
x
≤
B
≤
y
≤
C
≤
z
≤
D
)
x,y,z (A ≤ x ≤ B ≤ y ≤ C ≤ z ≤ D)
x,y,z(A≤x≤B≤y≤C≤z≤D)的三角形
解题思路
组
合
数
学
组合数学
组合数学
- 若枚举 x , y , z x,y,z x,y,z的值肯定是会超时的,所以我们可以枚举满足条件的 x + y x+y x+y的值
- 若想能 x , y , z x,y,z x,y,z组成三角形,那么需要 x + y > z x+y>z x+y>z, 又 z ∈ [ C , D ] z∈[C,D] z∈[C,D],所以 ( x + y ) m i n > C (x+y)_{min}>C (x+y)min>C
- 因为 x ∈ [ A , B ] x∈[A,B] x∈[A,B]且 y ∈ [ B , C ] y∈[B,C] y∈[B,C],又 ( x + y ) m i n > C (x+y)_{min}>C (x+y)min>C,所以 ( x + y ) m i n = m a x ( A + B , C + 1 ) (x+y)_{min}=max(A+B,C+1) (x+y)min=max(A+B,C+1),易得 x + y ∈ [ m a x ( A + B , C + 1 ) , B + C ] x+y∈[max(A+B,C+1),B+C] x+y∈[max(A+B,C+1),B+C]
- 然后
for
循环枚举可行的 x + y x+y x+y值,对于每个 i i i,满足条件的 z z z值范围为 [ C , i − 1 ] [C,i-1] [C,i−1],又因为 z m a x = D z_{max}=D zmax=D,所以可取 z z z的个数为min(D,i-1)-C+1
,即min(D+1,i)-C
- 因为
x
+
y
=
i
x+y=i
x+y=i,确定了其中一个数的值,另一个数的也就确定了,所以我们可以求出对于每个
i
i
i,可取
x
x
x值的个数,即是满足
x+y==i
的 x , y x,y x,y对数 - 容易看出 x x x的变化范围为 [ i − C , i − B ] [i-C,i-B] [i−C,i−B],不过 x x x还需要在 [ A , B ] [A,B] [A,B]之内,取相交区间就行了,所以 x ∈ [ m a x ( i − C , A ) , m i n ( i − B , B ) ] x∈[max(i−C,A),min(i−B,B)] x∈[max(i−C,A),min(i−B,B)],所以满足 x + y = i x+y=i x+y=i的 x , y x,y x,y对数就为 m i n ( i − B , B ) − m a x ( i − C , A ) + 1 min(i-B,B)-max(i-C,A)+1 min(i−B,B)−max(i−C,A)+1
- 根据乘法原理,可以可得对于当前
i
i
i满足条件的
x
,
y
,
z
x,y,z
x,y,z组数为
min(D+1,i)-C*min(i-B,B)-max(i-C,A)+1
,即可得到答案
附上代码
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) (x &(-x))
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const double PI=acos(-1.0);
const double e=exp(1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=2e5+10;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
inline void read(int &x){
char t=getchar();
while(!isdigit(t)) t=getchar();
for(x=t^48,t=getchar();isdigit(t);t=getchar()) x=x*10+(t^48);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int a,b,c,d,ans=0;
cin>>a>>b>>c>>d;
for(int i=max(c+1,a+b);i<=b+c;i++)
ans+=(min(d+1,i)-c)*(min(i-b,b)-max(i-c,a)+1);
cout<<ans<<endl;
return 0;
}