ACM元老的密码

出于在通信中隐藏信息的需要,人类在很久以前就学会了对传递的信息加密。

由于古时多数人并不识字,最早的秘密书写的形式只用到纸笔或等同物品,随着识字率提高,就开始需要真正的密码学了。最古典的两个加密技巧是:

  1. 移位式(Transpositioncipher):将字母顺序重新排列,例如‘help me’变成‘ehplem’;

  2. 替代式(substitutioncipher):有系统地将一组字母换成其他字母或符号,例如‘fly at once’变成‘gmz bu podf’(每个字母用下一个字母取代)。

这两种单纯的方式都不足以提供足够的机密性。凯撒密码是最经典的替代法,据传由古罗马帝国的皇帝凯撒所发明,用在与远方将领的通讯上,每个字母被往后位移三格字母所取代。

——维基百科《密码学》

NKU ACM也有自己的加密算法,称为NKU-ACM-ENCODE,具体操作如下:

有两张画有n*n个方格的纸,一张为已被加密的纸(下称加密纸),另一张为解密纸。加密纸中每个格子都有字母。解密纸由透明部分和不透明部分组成,用01矩阵表示,1代表透明,0代表不透明。

解密过程如下:

1   将解密纸放在加密纸上方,通过透明的地方可以看见一些字母,将这些字母按照从左到右,从上到下的顺序记录下来。

2   若解密纸能从右往左对折(右边在上,左边在下,折㾗只能在格子边缘),将解密纸从右往左对折。若解密纸朝上一面的某格透明,则将该格以下不透明的地方剪为透明。然后将解密纸按照从左到右,从上到下的顺序依次放在加密纸上(同一个格子不能被重复覆盖),按顺序记录字母,直至所有格子都被覆盖过。

  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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值