(虐心思维)CF-215C-Crosses(十字)

传送门

问题:

真的是被这个题意给弄懵了,纠结了一下午,最后是根据样例和代码才明白了是什么个意思。

给一个 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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值