AtCoder Grand Contest 025D-Choosing Points

Created with Raphaël 2.1.2 Atcoder Atcoder Jack Jack Can you do this difficult problem? Jack thinks about it No? How can I solve this problem? Just use your brain! 。。

(〃’▽’〃)

题解:
这种题看起来很简单,题解一看谁都会做,主要是考一种思考的过程,希望有帮助吧。
我们认为 ( 0 , 0 ) 一定可取,然后按照 2 d 来标记整张图。
先假设 d 2 = a 2 + b 2 ( a , b R ) ,这样只会多标记而不会漏掉。
C a s e :
d m o d 2 = 1 a b 一定一奇一偶,按国际象棋标记即可。
定左上角为 ( 0 , 0 )
0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0

d m o d 4 = 2 a b 一定都是奇数,隔一行标记一行即可。
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1

d m o d 4 = 0 ,此时 x 2 = y 2 + z 2 ( x = d 4 , y = a 2 , z = b 2 ) 。把 d , a , b 分别变成 x , y , z (相当于把 2 × 2 的区域看成一个格子),再进行上述操作即可。
0 0 1 1 0 0 1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 0 0 1 1 0 0

以下是 d = 16 的情况。
0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0

两个 d 分别处理以下,标记叠加后为 0 的就是可以放的,易证明空余位置一定是多于 n 2 的。任意取 n 2 个即可。
C o d e

#include<bits/stdc++.h>
#define N 605
using namespace std;
int f[N][N],n;
void work(int d)
{
    int t=0;
    while(d%4==0)
    {
        t++;
        d/=4;
    }
    if(d%2==1)
    {
        for(int i=0;i<2*n;i++)
            for(int j=0;j<2*n;j++)
                if(((i>>t)+(j>>t))%2==1)f[i][j]=1;
    }
    if(d%4==2)
    {
        for(int i=0;i<2*n;i++)
            for(int j=0;j<2*n;j++)
                if((i>>t)%2==1)f[i][j]=1;
    }
}
int main()
{
    int d1,d2;
    scanf("%d%d%d",&n,&d1,&d2);
    memset(f,0,sizeof(f));
    work(d1);work(d2);
    int sum=0;
    for(int i=0;i<2*n;i++)
        for(int j=0;j<2*n;j++)
            if(!f[i][j])
            {
                printf("%d %d\n",i,j);
                sum++;
                if(sum==n*n)return 0;
            }
}

猜你喜欢

转载自blog.csdn.net/qq_34531807/article/details/80917613