传送门
你有一个 2 n × m 2n\times m 2n×m 的网格,你需要给每个格子染上 n n n 种颜色之一,且对于每一个由格子组成的且边界平行于网格边界且边长大于等于 2 2 2 的矩形,它的四个角的格子的颜色不完全相同。
一行两个数 n n n 和 m m m 表示矩形的大小。
输出一个符合条件的 2 n × m 2n\times m 2n×m 的矩形,或者一个数 − 1 -1 −1 表示无解。如果有多组解,输出任意一种即可。
样例输入
3 3
样例输出
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Subtask 1( 10 10 10 分): n ≤ 2 , m ≤ 3 n\leq 2,m\leq 3 n≤2,m≤3。
Subtask 2( 20 20 20 分): n ≤ 5 , m ≤ 5 n\leq 5,m\leq 5 n≤5,m≤5。
Subtask 3( 30 30 30 分): n ≤ 50 , m ≤ 100 n\leq 50,m\leq 100 n≤50,m≤100。
Subtask 4( 40 40 40 分): n ≤ 100 , m ≤ 10000 n\leq 100,m\leq 10000 n≤100,m≤10000。
ahsdfz noip2020模拟
题解:
我们要求每列每种颜色必须出现两次
这样算出来的列数最多有 n × ( 2 n − 1 ) n\times (2n-1) n×(2n−1)列
然后我们这样染色:先找到 1 1 1至 2 n 2n 2n的一组匹配,然后每组匹配点的颜色要求相同,我们先给第一组染一号色,第二组染二号……然后我们环移一次后再染,一共能产生 n n n 组合法的对列的染色方案
接下来就是给一个 2 n 2n 2n 个点的完全图划分为 2 n − 1 2n-1 2n−1 组不同的完美匹配了
我们考虑留下第 2 n − 1 2n-1 2n−1 号点(点从 0 0 0 编号),然后第 i i i 轮我们把编号 j + k = i ( m o d ( 2 n − 1 ) ) j+k=i(mod(2n-1)) j+k=i(mod(2n−1))的 j j j 与 k k k 分为一组匹配,最后会剩余一个点,和 2 n − 1 2n-1 2n−1 连,显然匹配是不重复的
#include<bits/stdc++.h>
#define N 105
#define M 100005
using namespace std;
int read(){
int op=1,sum=0;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}
int cl[N<<1];
int ans[N<<1][M];
int main(){
int n=read(),m=read();
if(m>n*(2*n-1)){
puts("-1");return 0;}
for(int i=0;i<m;++i){
if(i%n==0){
int ct=0,re=i/n;
for(int j=0;j<2*n;++j)cl[j]=-1;
for(int j=0;j<2*n-1;++j){
if(cl[j]==-1){
int to=(i+2*n-1-j)%(2*n-1);
if(j==to)to=2*n-1;
cl[j]=cl[to]=ct++;
//if(i==2)cout<<j<<"->"<<to<<endl;
}
}
/*for(int j=0;j<2*n;++j){
cout<<cl[j]<<" ";
}
cout<<endl;*/
}
int re=i%n;
for(int j=0;j<2*n;++j){
ans[j][i]=(cl[j]+re)%n;
}
}
for(int i=0;i<2*n;++i){
for(int j=0;j<m;++j){
printf("%d ",ans[i][j]+1);
}
puts("");
}
return 0;
}