題面
Time limit per test: 1 second
Memory limit per test: 256 megabytes
Description
Like any unknown mathematician, Yuri has favourite numbers: A, B, C, and D, where A≤B≤C≤D. Yuri also likes triangles and once he thought: how many non-degenerate triangles with integer sides x, y, and z exist, such that A≤x≤B≤y≤C≤z≤D holds?
Yuri is preparing problems for a new contest now, so he is very busy. That's why he asked you to calculate the number of triangles with described property.
The triangle is called non-degenerate if and only if its vertices are not collinear.
Input
The first line contains four integers: A, B, C and D (1≤A≤B≤C≤D≤5⋅105) — Yuri's favourite numbers.
Output
Print the number of non-degenerate triangles with integer sides x, y, and z such that the inequality A≤x≤B≤y≤C≤z≤D holds.
Examples
input 1
1 2 3 4
output 1
4
input 2
1 2 2 5
output 2
3
input 3
500000 500000 500000 500000
output 3
1
Note
In the first example Yuri can make up triangles with sides (1,3,3), (2,2,3), (2,3,3) and (2,3,4).
In the second example Yuri can make up triangles with sides (1,2,2), (2,2,2) and (2,2,3).
In the third example Yuri can make up only one equilateral triangle with sides equal to 5⋅105.
題意
給定四個數 A B C D ,滿足 1≤A≤B≤C≤D≤5⋅105
問有多少組 x y z 使得
x ∈ [ A , B ]
y ∈ [ B , C ]
z ∈ [ C , D ]
且 x y z 嚴格構成一個三角形(三頂點不共線)
解題思路
別人的代碼好短qwq
沒看懂,自己想
明顯對於5e5的數據范圍,O(n2)的方法行不通
所以盡量通過公式入手並優化至 O(n)
對於三角形的性質,可得兩邊之和一定大於第三邊
又因為已經限制 x≤y≤z
所以只要保證 x+y>z 即可
對 x 進行枚舉,然后將 x A B C D 當作常量看
因為 z ∈ [ C , D ] ,所以對於 z 的最小值 C ,一定要讓 x+y>C 能夠成立才有可行解
得到 y>C-x 即 y>=C-x+1
所以可以設置 y 的最小值 ym 為 max( B , C-x+1 )
然后假設我們枚舉 y 從 ym 到 C
對於每一組 (x,y) ,由 x+y>z 得到此時 z 的最大值為 x+y-1
所以 z 的可行解共有 (x+y-1)-C+1 = x+y-C 種
又因為 z 的最大值為 D
一旦 x+y-1 大於D,則 z 的可行解種數將會變成一個常數 D-C+1
可以發現,在 x+y≤D 時,可行解種類數為 y+(x-C) ,是一個公差為 1 的等差數列(k=1的一次函數)
在 x+y>D 時,可行解種類數為 D-C+1 ,是一個常數
所以就可以把對於 y 的枚舉直接進行分類討論來線性處理
等差數列使用 “首項加尾項乘以項數除以2” ,常數直接乘上出現次數即可
一、z 的可行解均為常數
此時一定滿足條件 x+ym>D
,表示 y 取最小值時,z 的最大取值也符合題意
項數為 C-ym+1 ,常數為 D-C+1
故答案為 (C-ym+1)*(D-C+1)
二、z 的可行解均呈一次函數形式
此時一定不滿足條件 x+C>D
,即滿足x+C<=D
,表示 y 取最大值時,z 的最大取值也不符合題意
可以把一次函數的截距當作常數直接計算
ans = y+(x-C) ,截距為 x-C
因項數為 C-ym+1 ,所以對於截距,答案為 (C-ym+1)*(x-C)
然后看一次函數部分(等差數列),發現首項為 ym,尾項為 C
所以答案為 (ym+C)*(C-ym+1)/2
故答案為 (C-ym+1)*(x-C)+(C-ym+1)*(ym+C)/2
三、z 的可行解先呈一次函數形式再為一常數
此時一定滿足條件 x+C>D && x+ym<=D
,表示 y 取最大值時 z 的最大取值符合題意,但是 y 取最小值時,z 的最大取值不符合題意
所以分成兩部分看即可
由 x+y>D 得到函數的兩種圖像分界點為 y==D-x
在 [ ym , D-x ] 上呈一次函數,在 [ D-x+1 , C ] 上呈常數
對於常數部分,常數為 D-C+1 ,項數為 C-(D-x+1)+1 = C-D+x
故答案為 (C-D+x)*(D-C+1)
對於一次函數部分,項數為 D-x-ym+1
同樣分離常數部分與函數部分
常數部分值為 x-C ,答案為 (D-x-ym+1)*(x-C)
函數部分首項為 ym ,尾項為 D-x ,答案為 (D-x-ym+1)*(ym+D-x)/2
故答案為 (D-x-ym+1)*(x-C)+(D-x-ym+1)*(ym+D-x)/2
綜上,答案為 (C-D+x)*(D-C+1)+(D-x-ym+1)*(x-C)+(D-x-ym+1)*(ym+D-x)/2
完整程序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
ll A,B,C,D,ans=0,ym;
cin>>A>>B>>C>>D;
for(ll x=A;x<=B;x++)
{
ym=max(B,C-x+1);
if(x+C>D)
{
if(x+ym>D)
ans+=(C-ym+1)*(D-C+1);
else
ans+=(C-D+x)*(D-C+1)+(D-x-ym+1)*(x-C)+(D-x-ym+1)*(ym+D-x)/2;
}
else
ans+=(C-ym+1)*(x-C)+(C-ym+1)*(ym+C)/2;
}
cout<<ans<<'\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}