http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1117
1117: 网格中的三角形
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 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代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 typedef long long ll; 7 8 inline ll max(ll a, ll b) { 9 return a > b ? a : b; 10 } 11 12 inline ll min(ll a, ll b) { 13 return a < b ? a : b; 14 } 15 16 ll N, M, A, B; 17 18 ll solve (ll k) { 19 if (k < 0) 20 k = 0; 21 22 if (N > M) 23 swap(N, M); 24 25 ll ans = 0; 26 for (ll n = 1; n <= N; n++) { 27 for (ll m = 1; m <= M; m++) { 28 ll cnt = 0; 29 30 if (n * m <= k) 31 cnt += 2 * (n + m - 2); 32 33 ll l, r; 34 for (ll x = 0; x <= n; x ++) { 35 r = (m * x + k) / n; 36 37 if (r > m) 38 r = m; 39 40 ll t = m * x - k; 41 42 if(t <= 0) 43 l = 0; 44 else 45 l = (t - 1) / n + 1; 46 47 if(l <= r) 48 cnt += 2 * (r - l + 1); 49 } 50 51 for (ll x = 1; x < n; x++) { 52 ll tmp = n * m - x; 53 54 if (tmp <= k) 55 cnt += 4 * (m - 1); 56 else { 57 tmp = tmp - k; 58 ll u = m-1 - min(tmp / x + (tmp % x != 0), m-1); 59 cnt += 4 * u; 60 } 61 } 62 //printf("%lld %lld %lld ",n , m, cnt); 63 ans += cnt * (N - n + 1) * (M - m + 1); 64 } 65 } 66 return ans; 67 } 68 69 int main () { 70 int cas; 71 scanf("%d", &cas); 72 while (cas--) { 73 scanf("%lld%lld%lld%lld", &N, &M, &A, &B); 74 printf("%lld ", solve(B*2) - solve(A*2-1)); 75 } 76 return 0; 77 }