HHKB Programming Contest 2020 D - Squares(思维)

Problem Statement

Given are integers N , A , and B .

We will place a white square whose side is of length NN on the coordinate plane so that the vertices are at (0,0) , (N,0) , (0,N) , and (N,N)

Then, we will place a blue square whose side is of length A and a red square whose side is of length B so that these squares are inside the white square (including its boundary).

Here, each side of these squares must be parallel to the x - or y -axis.

Additionally, each vertex of red and blue squares must be at an integer point.

Find the number of ways to place red and blue squares so that they do not strictly overlap (they may share boundary with each other), modulo 1,000,000,007

Solve this problem for T test cases in each input file.

Constraints

  • 1≤T≤105
  • 1≤N≤109
  • 1≤A≤N
  • 1≤B≤N
  • All values in input are integers.

Output

For each test case, print the number of ways to place red and blue squares so that they do not strictly overlap, modulo 1,000,000,0071,000,000,007. Use one line for each test case.


Sample Input 1 Copy

Copy

3
3 1 2
4 2 2
331895368 154715807 13941326

Sample Output 1 Copy

Copy

20
32
409369707

For example, in the first test case, there are 99 ways to place the blue squares and 44 ways to place the red squares, ignoring overlap.

Wherever we place the red square, there are 44 ways to place the blue square so that it strictly overlaps with the red square.

Thus, there are 9×4−4×4=209×4−4×4=20 ways to place red and blue squares so that they do not strictly overlap.

Note that the squares may share boundary with each other. For example, when the bottom-left vertices of blue and red squares are (0,0)(0,0) and (0,1)(0,1), respectively, the squares do not strictly overlap.

题意:

在N*N的正方形区域内放置一个A*A和一个B*B的正方形,放置要求不能重叠且四个角要是整数点。

思路:
因为是在二维平面内放点,考虑起来比较复杂,我们可以把它投影到一维上。对于两个重叠的正方形投影到XY轴一定有X、Y轴的两根投影线段都会重叠,再看反面,如果有一个轴上的投影没有重叠则正方形一定是没重叠的。所以我们分下面两种情况统计答案:

(1)X轴上两线段不重合,Y轴投影随意放

因为线段都有两头,为简单起见我们只考虑两线段的左端点安放,对于A而言左端点坐标可以为[0,n-a],对于B而言左端点坐标为[0,n-b]
考虑到两线段的左右关系较为麻烦,我们不妨假设B线段一定在A线段的右边。
如果A左端点放置0,B可以放置[a,n-b],共n-b-a+1种放法
如果A左端点放置1,B可以放置[a+1,n-b],共n-b-a种放法
...
如果A左端点放置n-a-b,B可以放置在[n-b,n-b],共1种放法
我们记d=(n−a−b)d=(n−a−b),于是放法总数有(d+1)+(d)+(d−1)+...+1=(d+1)(d+2)2(d+1)+(d)+(d−1)+...+1=(d+1)(d+2)2
但是这只考虑了B在A右边的情况,B如果在A左边是相同情况,所以X轴上两线段不重合有(d+1)(d+2)(d+1)(d+2)种放置方式
Y轴因为是随意放置,利用乘法定理有(n−a+1)(n−b+1)(n−a+1)(n−b+1)中放法
故总放置方式数为(d+1)(d+2)(n−a+1)(n−b+1)(d+1)(d+2)(n−a+1)(n−b+1)

(2)X轴上两线段重合,Y轴投影不重合

第一种情况已经讨论了AB不重合的方案数为(d+1)(d+2)(d+1)(d+2),而总放法数为(n−a+1)(n−b+1)(n−a+1)(n−b+1),故重合的方案数为(n−a+1)(n−b+1)−(d+1)(d+2)(n−a+1)(n−b+1)−(d+1)(d+2)
而Y轴投影不重合的情况同X轴投影不重合相同,方案数为(d+1)(d+2)(d+1)(d+2)
故总放置方式数为(d+1)(d+2)[(n−a+1)(n−b+1)−(d+1)(d+2)](d+1)(d+2)[(n−a+1)(n−b+1)−(d+1)(d+2)]

综上,答案可用表达式(d+1)(d+2)(n−a+1)(n−b+1)+(d+1)(d+2)[(n−a+1)(n−b+1)−(d+1)(d+2)](d+1)(d+2)(n−a+1)(n−b+1)+(d+1)(d+2)[(n−a+1)(n−b+1)−(d+1)(d+2)]表示,化简结果为

ans=2(d+1)(d+2)(n−a+1)(n−b+1)−[(d+1)(d+2)]2ans=2(d+1)(d+2)(n−a+1)(n−b+1)−[(d+1)(d+2)]2

当然以上讨论都是建立在N*N的正方形区域是能放下两个正方形的,如果N<A+BN<A+B说明放不下要直接输出0。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;

int main() {
	ll t, n, a, b;
	scanf("%lld", &t);
	while(t--) {
		scanf("%lld%lld%lld", &n, &a, &b);
		if(a + b > n) {
			printf("0\n");
			continue;
		}
		ll tmp = (n - a - b) % mod;
		ll ans = (tmp + 1) % mod * (tmp + 2) % mod
				* (2 * (n - a + 1) % mod * (n - b + 1) % mod - (tmp + 1) % mod * (tmp + 2) % mod + mod) % mod;
		printf("%lld\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/109023463
今日推荐