N位的二进制串连续N次循环移位,得到N个二进制串。对其按照字典序排列,得到一个N*N的矩阵。告诉矩阵最后一列,求矩阵第一行。
拿这个题目例子讲解吧。
<span style="font-family:Microsoft YaHei;font-size:14px;">0 0 0 1 1
0 0 1 1 0
0 1 1 0 0
1 0 0 0 1
1 1 0 0 0</span>
我们看到最后一列是10010,因为是按照字典序排列,也就是0在1前面,那这个每一行的第一个数字肯定是从0到1的,因为是最高位嘛,所以我们将最后一列排序出第一列是00011。接下来就很神奇了。我们将最后一列的内容移到第一列,此时变成了:
<span style="font-family:Microsoft YaHei;font-size:14px;">1 0 0 0 1
0 0 0 1 1
0 0 1 1 0
1 1 0 0 0
0 1 1 0 0 </span>
这时我们知道了变换后矩阵的第一列和第二列,而根据字典序,我们需要对第一列进行重排序,即12345(行)变成了23514(行),而第二列这样变化后成为了00101,我们拿这个与原先的第二列比较,是不是一样?而第三列变成了01100,第4列变成了11000,发现第三列和原先的第二列一样,第四列和原先的第三列一样。所以我们可以通过两列推出所有列的情况。
这样子其实就可以做了,我们发现了第一列和最后一列有这样的对应关系。这样我们可以用next数组记录每一个01的相对位置对应情况,最后按照next数组的对应关系输出即可。
<span style="font-family:Microsoft YaHei;font-size:14px;">#include<stdio.h>
#include<stdlib.h>
# define MAX 3002
int data[MAX]={0};
int data1[MAX]={0};
int next[MAX]={0};
int cmp(const void *a ,const void *b){
return *(int *)a - *(int *)b;
}
int main(){
int n,i,zeroind=0,oneind=0,count,j;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&data[i]);
data1[i]=data[i];
}
qsort(data1,n,sizeof(int),cmp);
for(i=0;i<n;i++){
if(data1[i] == 0){
for(j=zeroind;j<n;j++){
if(data1[i]==data[j]) { next[i] = j; zeroind = j+1; break;}
}
}
else{
for(j=oneind;j<n;j++){
if(data1[i]==data[j]) { next[i] = j; oneind = j+1; break;}
}
}
}
count =0;i=0;
while(count < n-1){
printf("%d ",data[next[i]]);
i = next[i];
count++;
}
printf("%d",data[next[i]]);
printf("\n");
}</span>