题目大意
在 N N N 条水平线与 M M M 条竖直线构成的网格中,放 K K K 枚石子,每个石子都只能放在网格的交叉点上。
问在最优的摆放方式下,最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。
解题思路
显然,最优的摆放方式是所有的石子都聚集在一起。
所以摆放方式可以表示为一个长方形加上多出的几个石子。
设长方形的长为 x x x,宽为 y y y,则多出的石子个数为 k − x ∗ y k-x*y k−x∗y,暂且记为 z z z。
那么此时构成的长方形个数分为两种情况:
- y ≤ m y \leq m y≤m, C x 2 × C y 2 + y ∗ C z 2 C_{x}^{2} \times C_{y}^{2} + y*C_{z}^{2} Cx2×Cy2+y∗Cz2;
- y = m y=m y=m, C x 2 × C y 2 + x ∗ C z 2 C_{x}^{2} \times C_{y}^{2} + x*C_{z}^{2} Cx2×Cy2+x∗Cz2;
式子应该很好推的。
AC CODE
#include <bits/stdc++.h>
using namespace std;
int read()
{
int x = 0;
char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
int n, m, k;
long long ans;
long long C(int x)
{
return (x - 1) * x / 2;
}
long long solve(int x, int y)
{
if (y < m)
{
return C(x) * C(y) + y * C(k - x * y);
}
else
{
return C(x) * C(y) + x * C(k - x * y);
}
}
signed main()
{
n = read(), m = read(), k = read();
if (n > m)
swap(n, m);
for (int i = 2, r = min(n, (int)sqrt(k)); i <= r; ++i)
{
// cout << i << endl;
int x = min(m, k / i);
if (k >= x * (i + 1))
continue;
ans = max(ans, solve(i, x));
}
printf("%lld\n", ans);
return 0;
}