传送门
问题:
真的是被这个题意给弄懵了,纠结了一下午,最后是根据样例和代码才明白了是什么个意思。
给一个 n*m 的表格,和一个面积 s 。还规定了每个六元组表示的面积的规则。
目的是 求有多少个 六元组 (a,b,c,d,x0,y0) 能表示出面积是 s 的十字。。
(这个 十字 的定义,就是一个中心对称的十字图形,或者是一个矩形也可以,矩形也中心对称啊)
有一个六元组 (a, b, c, d, x0 , y0 )...对于坐标(x, y )表示的方格 只要满足下边 两个条件中的一个,
就是六元组表示的图形中的一个方格。
- |x0 - x| ≤ a 且 |y0 - y| ≤ b 或 |x0 - x| ≤ c 且 |y0 - y| ≤ d。。
- 对于一个六元组,这两个条件,每一个都能表示成一个矩形,因此,两个矩形才可能组成一个 十字啊~~~~~
比如 。这个十字是六元组 (0, 1, 1, 0, 2, 3) 在 3 × 4 的 表格上图样 , 面积是 5 .
输入:
三个整数 n m s (n,m <= 500)
输出:
一个整数,表示在给出的 n*m 的表格,有多少个六元组表示的十字的面积为 s。
样例:
Input
2 2 1
Output
4 (0, 0, 0, 0, 1, 1), (0, 0, 0, 0, 1, 2), (0, 0, 0, 0, 2, 1), (0, 0, 0, 0, 2, 2).
Input
3 4 5
Output
4
(0, 1, 1, 0, 2, 2), (0, 1, 1, 0, 2, 3), (1, 0, 0, 1, 2, 2), (1, 0, 0, 1, 2, 3).
分析:
六元组, 两个不等式条件, 理解这个是这道题的关键。
(a, b, c, d, x0 , y0 )
|x0 - x| ≤ a 且 |y0 - y| ≤ b 或 |x0 - x| ≤ c 且 |y0 - y| ≤ d。。
对于一个六元组,这两个条件,每一个都表示一个矩形,
第一个,表示的是 (2a+1) * (2b+1) 的矩形, 由 (a,b) 确定第一个矩形
第二个,表示的是(2c+1)*(2d+1) 的矩形, 由 (c,d) 确定第二个矩形
矩形的边长都是奇数,而且都是以 x0 ,y0 为对称轴的,其实这个 x0 y0没别的用了,
先枚举其中一个矩形的长和宽(i * j),对于每一个长和宽,可以的到一个面积 s1.。。。
1、当 s1 == s 时候,说明第二个矩形必须被第一个矩形包含。这一点很重要。然后就是确定第二个矩形可以有几个
也就是在(a, b) 确定的时候,确定(c, d) 可能的个数。因为他们的位置是可以交换的的,所以计算的时候
只需要先确定(a, b),最后再乘 2 就好了。
先假设,矩形二和矩形一完全重合,也就是
i = 2c + 1 j = 2d + 1
c = (i-1)/2 d = (j-1)/2
因为是包含关系,所以,c 的取值最多有 (i-1)/2 + 1 种,d 的取值最多有 (j-1)/2 + 1 种。
一共就是 ans =((i-1)/2 + 1) *( (j-1)/2 + 1)* 2 - 1种, 别忘了乘 2 ,因为可以交换。
别忘了 -1 .。。。。。。因为当两个矩形完全一样的时候 (a,b)=(c,d),只有一种。。。。。。。。
然后就是考虑 ,在 (n * m ) 的大矩形中,最多可以有 t 个 (i * j) 这样的小矩形。 ans *= t.!! ( 这个用F() 函数 )
2、当 s1 < s 时候,第一个矩形的面积比较小,此时不需要考虑矩形二包含矩形一的情况,因为在 分析 1 中最后乘二,已经
算上这一种了。 所以此时,只需要考虑 矩形二不被矩形一包含,它们是一个真正的十字。就像这个图
矩形一的面积是 s1 = 3 , 需要的面积 s = 5 .。。 。。。所以 就有了这个十字架。。。。
在这种情况下,还需要再增加的面积是s2 = (s - s1 ), 因为这个 s2 一定是对称分布在 矩形一的两侧。
所以 s2 一定是偶数, 面积有了,还需要再确定一边。
这里需要自己规定一下,比如用 矩形一的长 j 来限制矩形二的长 k ,,
又因为 一定不会 包含 矩形一,,所以 ,k 一定是小于 j 的。。。。
同样,k 一定是奇数。。我们枚举每一个 k , 找到所有合适的 k ,
k一定需要是 s2的因数。。。 然后可以求出 s2 的总宽 w1 = s2 / k,
因为 s2 是分布在矩形一两边的,所以 w1 再加上矩形一的宽 i ,,就是矩形二的宽 w = s2 / k + i,
矩形二的宽 w 一定是小于等于 n 的。。。。。。。
满足上面五个蓝字条件的 k ,就是我们要找的 k 。。。。。。。。。。。。。
这样就找到了我们需要的一个十字,。。这个十字是在一个 (w * j) 的矩形中的!!!!!!!~~~
然后就是求 在 (n * m) 大矩形中,有几个 ( w * j ) 的小矩形,。。。。
最后别忘了 *2 ,,,,因为 两个矩形是可以交换位置的。。。。。。。。。
这样的思路绝对不会有重复和遗漏。。。。。。
F() 函数, 计算 (n * m) 大矩形中 , 最多有几个( i * j) 的小矩形。
long long F(int i,int j)
{
return (n - i + 1) * (m - j + 1 );
}
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX = 2e5 + 5;
int n,m,s,s1;
long long F(int h,int w)
{
return (n - h + 1) * (m - w + 1 );
}
long long ans;
int main()
{
cin >> n >> m >> s;
for(int i = 1; i <= n; i += 2) {
for(int j = 1; j <= m; j += 2) {
s1=i*j;
if(s1 == s) {
int t = ((i - 1)/2+1) * ((j - 1)/2+1) * 2 - 1;
ans += t * F(i,j);
}
else if(s > s1) {
s1 = s - s1; // 还需要的面积
for(int k = 1; k < j; k += 2) {//烧脑
if((s1%2==0) && s1%k==0 && i+s1/k<=n)
ans += 2*F(i+s1/k,j);
}
}
}
}
cout << ans << endl;
return 0;
}