版权声明:本文为博主原创文章,你们可以随便转载 https://blog.csdn.net/Jaihk662/article/details/83933734
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4063
题意:
给你n和k,都小于1000,构造一个k*n的数组满足
- 如果a[p][x]=y,那么a[p][y]必须等于x,1≤p≤k,1≤x,y≤n
- 每一列所有数字都必须不相同,每一行所有数字也都必须不相同,且都在[1,n]范围内
- 对于任意两行i, j,如果a[i][x] = y, a[i][y] = x, a[i][c] = d,a[i][d] = c,且a[j][x] = c,a[j][c] = x,那么必须满足a[j][y] = d,且a[j][d] = y
- 字典序最小
构造不出来输出Impossible
思路:
构造题嘛,理论上不停拿数据测AC代码看输出就会做了,因为重要的是怎么构造
这题可以预处理1024*1024的情况,然后对于每次询问n, k,如果可以直接输出前n行前k列就可以了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
int len, ans[1038][1038];
void Gao(int x, int y, int n, int p)
{
int i, j;
if(n==1)
{
ans[x][y] = p;
return;
}
n /= 2;
Gao(x, y, n, p);
Gao(x, y+n, n, p+n);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
ans[x-1+i+n][y-1+j] = ans[x-1+i][y-1+j+n];
ans[x-1+i+n][y-1+j+n] = ans[x-1+i][y-1+j];
}
}
}
int main(void)
{
int T, n, k, i, j;
Gao(1, 1, 1024, 1);
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &k);
if(k>=(n&-n))
printf("Impossible\n");
else
{
len = n;
for(i=2;i<=k+1;i++)
{
printf("%d", ans[i][1]);
for(j=2;j<=n;j++)
printf(" %d", ans[i][j]);
puts("");
}
}
}
return 0;
}