时间限制: 1000ms 内存限制: 256MB
描述
在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子,每个石子都只能放在网格的交叉点上。问在最优的摆放方式下,最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。
输入
输入文件包含多组测试数据。
第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。
每组数据为三个用空格隔开的整数 N,M,K。
输出
对于每组测试数据,输出一行"Case #X: Y",其中X表示测试数据编号,Y表示最多能找到的符合条件的长方形数量。所有数据按读入顺序从1开始编号。
数据范围
1 ≤ T ≤ 100
0 ≤ K ≤ N * M
小数据:0 < N, M ≤ 30
大数据:0 < N, M ≤ 30000
样例输入
3
3 3 8
4 5 13
7 14 86
样例输出
Case #1: 5
Case #2: 18
Case #3: 1398
需要用到组合数学,还是破费了一番周折。思路就是先找到在网格中最大能形成的长方形矩阵的长x和宽y,算出剩余石子l,根据公式xy(x-1)(y-1)/4算出最大长方形矩阵可形成的长方形数量(正方形也属于长方形),再算出最长边加入剩余石子后可形成的长方形数量x * (l * (l-1)/2),他们的和即为结果。
描述
在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子,每个石子都只能放在网格的交叉点上。问在最优的摆放方式下,最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。
输入
输入文件包含多组测试数据。
第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。
每组数据为三个用空格隔开的整数 N,M,K。
输出
对于每组测试数据,输出一行"Case #X: Y",其中X表示测试数据编号,Y表示最多能找到的符合条件的长方形数量。所有数据按读入顺序从1开始编号。
数据范围
1 ≤ T ≤ 100
0 ≤ K ≤ N * M
小数据:0 < N, M ≤ 30
大数据:0 < N, M ≤ 30000
样例输入
3
3 3 8
4 5 13
7 14 86
样例输出
Case #1: 5
Case #2: 18
Case #3: 1398
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <math.h>
#include <fstream>
using namespace std;
typedef long long LL;
int main()
{
int T,x;
while(scanf("%d",&T)==1)
{
for(x=1;x<=T;x++)
{
LL N,M,K;
scanf("%lld%lld%lld",&N,&M,&K);
if(N>M)//让M大于N
{
N=M+N;
M=N-M;
N=N-M;
}
int n=sqrt(K)>N?N:sqrt(K);
int m=M;
while(n * m>K)
m--;
LL ans=0;
LL res=0;
while(n>=2&&m<=M)
{
LL k=K;
res += (n*m*(n-1)*(m-1))>>2 ;
k -= m*n;
if(m < M)
res+=(m*k*(k-1))>>1;
else
res+=(n*k*(k-1))>>1;
ans=res>ans?res:ans;
res=0;
n --;
m=K/n;
}
printf("Case #%d: %lld\n",x,ans);
}
}
return 0;
}
需要用到组合数学,还是破费了一番周折。思路就是先找到在网格中最大能形成的长方形矩阵的长x和宽y,算出剩余石子l,根据公式xy(x-1)(y-1)/4算出最大长方形矩阵可形成的长方形数量(正方形也属于长方形),再算出最长边加入剩余石子后可形成的长方形数量x * (l * (l-1)/2),他们的和即为结果。