http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1117
1117: 网格中的三角形
Time Limit: 3 Sec Memory Limit: 64 MB
Submit: 35 Solved: 12
[Submit][Status][Web Board]
Description
有一个n行m列单位正方形组成的网格。不难发现一共有n+1条横线,m+1条竖线和它们形成的(n+1)(m+1)个交叉点。你可以选择三个不共线的交叉点,形成一个三角形。比如当n=m=1时,一共有4个交叉点,可以形成4个三角形。
问:有多少个三角形的面积在A和B之间(包含A和B)。
Input
输入第一行为数据组数T (T<=25)。每组数据为四个整数n, m, A, B (1<=n, m<=200, 0<=A<B<=nm)。
Output
对于每组数据,输出面积在A和B之间的三角形个数。
Sample Input
4
1 1 0 1
1 2 1 2
10 10 20 30
12 34 56 78
Sample Output
4
6
27492
1737488
HINT
Source
AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std;
typedef long long ll; inline ll max(ll a, ll b) {
return a > b ? a : b;
} inline ll min(ll a, ll b) {
return a < b ? a : b;
} ll N, M, A, B; ll solve (ll k) {
if (k < )
k = ; if (N > M)
swap(N, M); ll ans = ;
for (ll n = ; n <= N; n++) {
for (ll m = ; m <= M; m++) {
ll cnt = ; if (n * m <= k)
cnt += * (n + m - ); ll l, r;
for (ll x = ; x <= n; x ++) {
r = (m * x + k) / n; if (r > m)
r = m; ll t = m * x - k; if(t <= )
l = ;
else
l = (t - ) / n + ; if(l <= r)
cnt += * (r - l + );
} for (ll x = ; x < n; x++) {
ll tmp = n * m - x; if (tmp <= k)
cnt += * (m - );
else {
tmp = tmp - k;
ll u = m- - min(tmp / x + (tmp % x != ), m-);
cnt += * u;
}
}
//printf("%lld %lld %lld\n",n , m, cnt);
ans += cnt * (N - n + ) * (M - m + );
}
}
return ans;
} int main () {
int cas;
scanf("%d", &cas);
while (cas--) {
scanf("%lld%lld%lld%lld", &N, &M, &A, &B);
printf("%lld\n", solve(B*) - solve(A*-));
}
return ;
}