AT_agc025_d [AGC025D] Choosing Points

AT_agc025_d\(\mathbf{} \begin{Bmatrix} \frac{{\Large AGC025D} }{{\color{Red}\Large Solution} }\mathbf{} {No.9} \end{Bmatrix}\times{}\) NeeDna

题目解释:要从一个矩阵中找出至少n个点使得任意两点之间距离不为 $\sqrt{D_1} $ 或 $\sqrt{D_2} $。

思路:我们先假设只有 $\sqrt{D_1} $ 一个限制。那么我们就可以把矩阵中的点分组且组中的点互不违反规则,然后随便选一组即可。思考每一组的性质,这里有一个结论就是一个人矩阵只有两组,也就是矩阵可以构成二分图。

原理:因为假如一个正多边形有奇数条边,那么这个正多边形的每个角的 $\tan \alpha $ 都为无理数,可以感性理解一下。

我们回到题目,有两组限制,那么我们就每一个限制都分成 \(2\) 组,那么对于每个点就会有 \(4\) 种情况,每一种情况中的点就是符合题目要求的,因为有 \(2n\times2n\div4=n ^{2}\) 直接输出最大的一组即可。

考虑如何处理分组,可以用dfs,也可以用余数分类讨论,也是本题解的做法。简单来说就是构造 \(x^{2} +y^{2}=D\)(注意此时 \(D\) 是缩放过的,\(x\)\(y\) 同理)然后分析 \(x\)\(y\) 的偶性。

  1. \(D\equiv 1 \pmod{4}\)\(x+y\) 奇偶性相同的点对在一组。

  2. \(D\equiv 3 \pmod{4}\)\(x\) 奇偶性相同的点对在一组。

ac code:

#include <bits/stdc++.h>
using namespace std;
const int N=6e2+10;
int n,d1,d2,t1,t2,f[N][N][2],t[5],cnt; 
int main(){
    cin>>n>>d1>>d2;
    while(!(d1%4)) d1/=4,t1++;while(!(d2%4)) d2/=4,t2++;
    for(int i=1;i<=n*2;i++)
    	for(int j=1;j<=n*2;j++){
        	if(d1%4==1) f[i][j][0]=((i>>t1)+(j>>t1))&1;
        	else f[i][j][0]=(i>>t1)&1;
        	if(d2%4==1) f[i][j][1]=((i>>t2)+(j>>t2))&1;
        	else f[i][j][1]=(i>>t2)&1;
        	t[((f[i][j][0])<<1)+(f[i][j][1])]++;}
    for(int i=0;i<=3;i++){if(t[i]>=n*n) t1=(i>>1),t2=i%2;}   
    for(int i=1;i<=n*2;i++)
    	for(int j=1;j<=n*2;j++)
    		if(f[i][j][0]==t1&&f[i][j][1]==t2&&cnt<n*n)
    			cnt++,cout<<i-1<<" "<<j-1<<'\n';
    return 0;
}
posted @ 2025-05-30 20:50  NeeDna  阅读(7)  评论(0)    收藏  举报