2018.07.12 atcoder Choosing Points(数学分析好题)

传送门
一句话题意:给出 n,d1,d2 n , d 1 , d 2 ,需要求出 n2 n 2 个点使得每两点之间的距离不为 d1 d 1 或者 d2 d 2

好吧这题第一眼直接暴力建图然后发现时间复杂度上天。显然不能暴力建图,看来 d1,d2 d 1 , d 2 应该具有一些奇妙的性质。

那么我们对 d1,d2 d 1 , d 2 来进行奇偶分析。
我们让 d d 表示两点之间的距离,a表示两点之间的横坐标差, b b 表示两点之间的纵坐标差。那么不合法的情况就满足d2=a2+b2。好的讨论开始。

  • d2 d 2 是一个奇数,显然 a a b是一奇一偶的,这样的话就可以类似在棋盘上黑白染色一样,只染同一种颜色,然后任意两点间的距离的平方就都是偶数了。
  • d2 d 2 mod m o d 4=2 4 = 2 ,可以推出 a a b都是奇数,于是一排染色,一排不染色,这样的话任意 a a ,b是一奇一偶或者两个偶。
  • 最后一种情况, d2 d 2 mod m o d 4=0 4 = 0 ,这是最不好解决的情况,于是果断将每个 22 2 ∗ 2 的格子都缩小成一个格子,然后将 d d 缩小一半按前两种情况处理即可(反正题目保证可以找到nn格子,因此只用缩小一次)。

    代码如下:

#include<bits/stdc++.h>
#define eps 1e-7
using namespace std;
int n,d1,d2,cnt=0;
bool f[1005][1005];
inline void solve(int d){
    int b=0;
    while(!(d%4))d>>=2,++b;
    if(d&1){
        for(int i=0;i<(n<<1);++i)
            for(int j=0;j<(n<<1);++j)
                if(((i>>b)+(j>>b))&1)f[i][j]=true;
        return;
    }
    for(int i=0;i<(n<<1);++i)
        for(int j=0;j<(n<<1);++j)
            if((i>>b)&1)f[i][j]=true;
}
int main(){
    scanf("%d%d%d",&n,&d1,&d2);
    solve(d1),solve(d2);
    for(int i=0;i<(n<<1);++i)
        for(int j=0;j<(n<<1);++j)
            if(cnt<n*n&&!f[i][j])printf("%d %d\n",i,j),++cnt;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值