Points Construction Problem(构造)

Points Construction Problem(构造)

思路:构造。

考虑:如下无解的情况。

1.每个黑格子的贡献只能是 4 , 2 , 0 4,2,0 ,所以答案只能是偶数。

2.且 n n 个格子最多贡献 4 n 4n 个,则必须满足 m 4 n m\leq4n

3.考虑我们能构造 m m 的下界:

一条长为 x x 的直链的贡献为: 2 x + 2 2x+2 ,一条长为 x x ,宽为 y y ,形如 L L 的链贡献为: 2 ( x + y ) 2(x+y) ,显然若成为一个长为 x x ,宽为 y y 的矩阵后贡献仍然不变,因为每增加一个格子,贡献 + 2 , 2 +2,-2 是不影响的,所以需要满足 x y n xy\geq n ,且 2 ( x + y ) 2(x+y) 最小。

由基本不等式可知: 2 ( x + y ) m 2 × 2 x y 4 n 2(x+y)\geq m\geq2\times 2\sqrt{xy}\geq 4\sqrt{n}

所以 m 4 n m\geq4\sqrt{n} 。即当 16 n > m 2 16n>m^2 是无解的。

接下来分两种情况构造:

1. m > 2 n + 2 1.m>2n+2

我们可以构造一条一直链和若干个贡献为 4 4 的点。

设贡献为 4 4 的点个数为 x x ,则直链长度为 y = n x y=n-x

总贡献为:

4 x + 2 y + 2 = m 4 x + 2 ( n x ) + 2 = m x = m ( 2 n + 2 ) 2 4x+2y+2=m\\4x+2(n-x)+2=m\\x=\dfrac{m-(2n+2)}{2}

因为 m > ( 2 n + 2 ) , m m>(2n+2),m 为偶数,显然 x x 必定有解。

2. 2. m 2 n + 2 m\leq 2n+2 的情况。

考虑类比无解的情况 3 3

我们构造一条 L L 形状的链,然后不断填充就可以了。

即:用 x + y 1 x+y-1 个点构造出 2 ( x + y ) = m 2(x+y)=m 贡献,然后剩下的点 r e s t = n ( x + y 1 ) rest=n-(x+y-1) 用来填充矩形即可。

m 2 n + 2 m 2 n + 1 m\leq2n+2\rightarrow \dfrac{m}{2}\leq n+1

即我们构造出长和宽和为 m 2 \dfrac{m}{2} L L 链,用 m 2 1 \dfrac{m}{2}-1 个点 n \leq n ,显然是有解的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        if(m&1||m>4*n||n*16>m*m) puts("No");
        else {
            puts("Yes");
            if(m>2*n+2){
                int x=(m-(2*n+2))/2,y=n-x;
                for(int i=1;i<=x;i++) printf("1 %d\n",(i<<1));
                for(int i=1;i<=y;i++) printf("3 %d\n",i);
            }
            else {
                int x=m/4,y=m/2-x;
                 for(int i=1;i<=x;i++) printf("%d 1\n",i);
                 for(int j=2;j<=y;j++) printf("1 %d\n",j);
                int rest=n-(x+y-1);
                for(int i=2;i<=x&&rest>0;i++)
                    for(int j=2;j<=y&&rest>0;j++,rest--)
                        printf("%d %d\n",i,j);
                }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107443283