传送门
一句话题意:给出
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
表示两点之间的距离,表示两点之间的横坐标差,
b
b
表示两点之间的纵坐标差。那么不合法的情况就满足。好的讨论开始。
- 若 d2 d 2 是一个奇数,显然 a a 和是一奇一偶的,这样的话就可以类似在棋盘上黑白染色一样,只染同一种颜色,然后任意两点间的距离的平方就都是偶数了。
- 若 d2 d 2 mod m o d 4=2 4 = 2 ,可以推出 a a 和都是奇数,于是一排染色,一排不染色,这样的话任意 a a ,是一奇一偶或者两个偶。
最后一种情况, d2 d 2 mod m o d 4=0 4 = 0 ,这是最不好解决的情况,于是果断将每个 2∗2 2 ∗ 2 的格子都缩小成一个格子,然后将 d d 缩小一半按前两种情况处理即可(反正题目保证可以找到格子,因此只用缩小一次)。
代码如下:
#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;
}