C. Count Triangles(组合数学)
传送门
思路:考虑所有的
x+y组成的可行解。
显然
x,y,z组成三角形
→x+y>z, 因为
zmin=c,所以
(x+y)min>c.
又因为
xmin=a,ymin=b.所以
x+y具有可行解的最小值为
max(c+1,a+b).
最大值即
b+c.
所以
x+y∈[max(c+1,a+b),b+c]
接下来考虑每种
x+y对答案的贡献,首先考虑对于当前
i=x+y,
z的取值。
显然
z只能取
c,c+1…i−2,i−1.又因为
cmax=d.所以
z可选的个数为
cntz=min(d,i−1)−c+1=min(d+1,i)−c.
接下来考虑
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≤c所以y的取值的范围为:[max[i−c,a],min[i−b,b]]即x+y可选的个数为:cntx+y=min(i−b,b)−max(i−c,a)+1个。
根据乘法原理可得当前
x+y的贡献为:
cntx+y×cntz
综上可以通过遍历
x+y得到答案。
时间复杂度:
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;
}