【Codeforces Round #643 (Div. 2) C】Count Triangles
阿新 • • 發佈:2020-12-06
題目連結
翻譯
讓你找 \(3\) 條邊 \(x,y,z\), 要求 \(A\le x\le B\le y\le C\le z\le D\)
且 \(x,y,z\) 能組成三角形。
問你這樣的 \(x,y,z\) 的個數。
題解
對於最後選出來的邊,我們只需要關注 \(x+y\) 是不是大於 \(z\) 就好了 (兩邊之和大於第三邊)。
因為 \(x<=y<=z\) 且 \(x,y,z\) 都是正整數。所以 \(y+z>x\) 和 \(z+x>y\) 恆成立。
首先, 比較明顯的是我們可以先列舉其中一條邊 \(x\) 。
然後 \(y\) 的話會從 \(B\) 到 \(C\)
這個區間和 \([C,D]\) 這個區間的相交情況有 \(5\) 種可能(除去完全在 \([C,D]\) 左邊這種情況不可能)。
分別把這 \(5\) 種情況畫出來, 算一下 \(y\) 在這個區域裡面對答案的貢獻就好了(\(z\) 的值要比 \(x+y\) 來的小)。
會對應很多的類似1,2,3,4...
的公差為 \(1\) 的等差數列(用求和公式算一下答案)。以及整個 \([C,D]\) 區域的值都可以取的情況(x+y>D)。
強烈建議畫個數軸來討論!
程式碼
#include <bits/stdc++.h> #define LL long long using namespace std; LL a,b,c,d; int main(){ ios::sync_with_stdio(0),cin.tie(0); cin >> a >> b >> c >> d; LL ans = 0; for (LL x = a;x <= b;x++){ if (x+b>d){ ans += (d-c+1)*(c-b+1); continue; } if (x+b <= c && x+c <= d){ ans += (1+x)*x/2; } if (x+b <= c && x+c > d){ ans += (1+d-c)*(d-c)/2+(x+c-d)*(d-c+1); } if (x+b > c && x+c <= d){ LL a1 = x+b-c,n = c-b+1; LL an = a1 + n - 1; ans += (a1+an)*n/2; } if (x+b > c && x+c > d){ LL a1 = x + b - c; LL n = (d-x-b+1); LL an = a1 + n-1; ans += (a1+an)*n/2; ans += (x+c-d)*(d-c+1); } } cout << ans << endl; return 0; }