出于在通信中隐藏信息的需要,人类在很久以前就学会了对传递的信息加密。
由于古时多数人并不识字,最早的秘密书写的形式只用到纸笔或等同物品,随着识字率提高,就开始需要真正的密码学了。最古典的两个加密技巧是:
-
移位式(Transpositioncipher):将字母顺序重新排列,例如‘help me’变成‘ehplem’;
-
替代式(substitutioncipher):有系统地将一组字母换成其他字母或符号,例如‘fly at once’变成‘gmz bu podf’(每个字母用下一个字母取代)。
这两种单纯的方式都不足以提供足够的机密性。凯撒密码是最经典的替代法,据传由古罗马帝国的皇帝凯撒所发明,用在与远方将领的通讯上,每个字母被往后位移三格字母所取代。
NKU ACM也有自己的加密算法,称为NKU-ACM-ENCODE,具体操作如下:
有两张画有n*n个方格的纸,一张为已被加密的纸(下称加密纸),另一张为解密纸。加密纸中每个格子都有字母。解密纸由透明部分和不透明部分组成,用01矩阵表示,1代表透明,0代表不透明。
解密过程如下:
1 将解密纸放在加密纸上方,通过透明的地方可以看见一些字母,将这些字母按照从左到右,从上到下的顺序记录下来。
2 若解密纸能从右往左对折(右边在上,左边在下,折㾗只能在格子边缘),将解密纸从右往左对折。若解密纸朝上一面的某格透明,则将该格以下不透明的地方剪为透明。然后将解密纸按照从左到右,从上到下的顺序依次放在加密纸上(同一个格子不能被重复覆盖),按顺序记录字母,直至所有格子都被覆盖过。
-
若解密纸能从下往上对折,将解密纸从下往上对折,余下同2。
-
重复2,3步操作直至解密纸不能被对折。
一天,ACM元老给Lee发了一份重要文件,但打开文件需要密码。元老同时给了Lee一张解密纸和加密纸,Lee知道元老们用NKU-ACM-ENCODE加密了密码,但Lee是个很懒的家伙,所以他打算找个勤劳勇敢的同学来帮他解密。于是他找到了你,请勤劳勇敢的你帮帮Lee吧!
Input
第一行输入一个正整数n(1<=n<=550),意义如上文所述。接下来的n行每行输入n个字母,表示加密纸。接下来的n行每行输入n个字符(0或1),表示解密纸。
Output
输出一行,即打开文件的密码。
Sample Input
4
ABCD
EFGH
IJKL
MNOP
0000
0100
0010
0000
Sample Output
FKJLFHNPEFGHMNOPABCDEFGHIJKLMNOP
#include<stdio.h>
#include<stdlib.h>
#define MAX 550
int size;
int b_row,b_col;
char temp[MAX][MAX];
void r2L(char (*b)[MAX])
{
int i,j;
for(i=0;i<b_row;i++)
for(j=0;j<b_col/2;j++)
{
temp[i][j]=b[i][b_col-j-1];
if(b[i][b_col-j-1]=='1')
b[i][j]='1';
}
b_col=b_col/2;
}
void d2U(char (*b)[MAX])
{
int i,j;
for(i=0;i<b_row/2;i++)
for(j=0;j<b_col;j++)
{
temp[i][j]=b[b_row-i-1][j];
if(b[b_row-i-1][j]=='1')
b[i][j]='1';
}
b_row=b_row/2;
}
int canDo_rl(char (*b)[MAX])
{
if(b_col%2==0)
return 1;
else
return 0;
}
int canDo_du(char (*b)[MAX])
{
if(b_row%2==0)
return 1;
else
return 0;
}
void record(char a[][MAX])
{
int i,j;
int m,n;
for(i=0;i<size/b_row;i++)
for(j=0;j<size/b_col;j++)
{
for(m=0;m<b_row;m++)
for(n=0;n<b_col;n++)
if(temp[m][n]=='1')
printf("%c",a[m+i*b_row][n+j*b_col]);
}
}
int main()
{
int i,j;
char a[MAX][MAX];
char b[MAX][MAX];
scanf("%d",&size);
getchar();
b_row=size;
b_col=size;
//输入a[][]
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
scanf("%c",&a[i][j]);
getchar();
}
//输入b[][]
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
scanf("%c",&b[i][j]);
getchar();
}
//temp[][]赋初值,b[][]
for(i=0;i<b_row;i++)
for(j=0;j<b_col;j++)
temp[i][j]=b[i][j];
//对折,记录
record(a);
while(1)
{
if(canDo_rl(b))
{
r2L(b);
record(a);
}
if(canDo_du(b))
{
d2U(b);
record(a);
}
if(!canDo_rl(b)&&!canDo_du(b))
break;
}
//system("pause");
printf("\n");
return 0;
}