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

C. Count Triangles

题目链接-C. Count Triangles
Codeforces Round #643 (Div. 2) C. Count Triangles_第1张图片
Codeforces Round #643 (Div. 2) C. Count Triangles_第2张图片
题目大意
给你四个数 A , B , C , D A,B,C,D ABCD,求有多少个三边为 x , y , z ( A ≤ x ≤ B ≤ y ≤ C ≤ z ≤ D ) x,y,z (A ≤ x ≤ B ≤ y ≤ C ≤ z ≤ D) xyzAxByCzD的三角形

解题思路
组 合 数 学 组合数学

  • 若枚举 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,i1],又因为 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] [iC,iB],不过 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(iC,A),min(iB,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(iB,B)max(iC,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
#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;
}

你可能感兴趣的:(codeforces,数论)