C. Count Triangles(组合数学)
思路:考虑所有的 x + y x+y x+y组成的可行解。
显然 x , y , z x,y,z x,y,z组成三角形 → x + y > z \rightarrow x+y>z →x+y>z, 因为 z m i n = c z_{min}=c zmin=c,所以 ( x + y ) m i n > c (x+y)_{min}>c (x+y)min>c.
又因为 x m i n = a , y m i n = b x_{min}=a,y_{min}=b xmin=a,ymin=b.所以 x + y x+y x+y具有可行解的最小值为 m a x ( c + 1 , a + b ) max(c+1,a+b) max(c+1,a+b).
最大值即 b + c b+c b+c.
所以 x + y ∈ [ m a x ( c + 1 , a + b ) , b + c ] x+y\in[max(c+1,a+b),b+c] x+y∈[max(c+1,a+b),b+c]
接下来考虑每种 x + y x+y x+y对答案的贡献,首先考虑对于当前 i = x + y i=x+y i=x+y, z z z的取值。
显然 z z z只能取 c , c + 1 … i − 2 , i − 1 c,c+1\dots i-2,i-1 c,c+1…i−2,i−1.又因为 c m a x = d c_{max}=d cmax=d.所以
z z z可选的个数为 c n t z = m i n ( d , i − 1 ) − c + 1 = m i n ( d + 1 , i ) − c cnt_z=min(d,i-1)-c+1=min(d+1,i)-c cntz=min(d,i−1)−c+1=min(d+1,i)−c.
接下来考虑 x + y x+y x+y可选的个数.
y
:
[
b
,
…
,
c
]
x
:
[
a
,
…
,
b
]
对
每
个
y
,
x
的
对
应
值
为
[
i
−
c
,
…
,
i
−
b
]
.
因
为
i
≥
a
+
b
,
i
≤
b
+
c
⇒
i
−
b
≥
a
,
i
−
c
≤
b
所
以
x
的
取
值
的
范
围
为
:
[
m
a
x
[
i
−
c
,
a
]
,
m
i
n
[
i
−
b
,
b
]
]
即
x
+
y
可
选
的
个
数
为
:
c
n
t
x
+
y
=
m
i
n
(
i
−
b
,
b
)
−
m
a
x
(
i
−
c
,
a
)
+
1
个
。
y:[b,\dots,c]\\x:[a,\dots,b]\\对每个y,x的对应值为[i-c,\dots,i-b].\\因为i\geq a+b,i\leq b+c\Rightarrow i-b\geq a,i-c\leq b\\所以x的取值的范围为:[max[i-c,a],min[i-b,b]]\\即x+y可选的个数为:cnt_{x+y}=min(i-b,b)-max(i-c,a)+1个。
y:[b,…,c]x:[a,…,b]对每个y,x的对应值为[i−c,…,i−b].因为i≥a+b,i≤b+c⇒i−b≥a,i−c≤b所以x的取值的范围为:[max[i−c,a],min[i−b,b]]即x+y可选的个数为:cntx+y=min(i−b,b)−max(i−c,a)+1个。
根据乘法原理可得当前
x
+
y
x+y
x+y的贡献为:
c
n
t
x
+
y
×
c
n
t
z
cnt_{x+y}\times cnt_z
cntx+y×cntz
综上可以通过遍历
x
+
y
x+y
x+y得到答案。
时间复杂度: O ( m a x ( b , c − a + 1 ) ) O(max(b,c-a+1)) O(max(b,c−a+1))
AC代码:
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
signed main(){
ll a,b,c,d;
cin>>a>>b>>c>>d;
ll ans=0;
for(ll 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;
}