C. Count Triangles(组合数学)

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+1i2,i1.又因为 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,i1)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 ≤ c 所 以 y 的 取 值 的 范 围 为 : [ 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 c\\所以y的取值的范围为:[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]yx[ic,,ib].ia+b,ib+ciba,iccy[max[ic,a],min[ib,b]]x+y:cntx+y=min(ib,b)max(ic,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,ca+1))

AC代码:

#include
#include
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;
}

你可能感兴趣的:(组合数学)