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>