您的位置:首页 > 其它

Zoj 1009 Enigma

2014-08-09 01:30 288 查看


从上面明文到密文的转换可以得出这样的规律 密文->明文 :
ABCDEF
+1-1+3-10-2
即密文A ->B,C->F,E->E,

每次rotor旋转一格 则等价于
ABCDEF
-2+1-1+3-10
此时C->B 同理rotor再旋转一次 有
ABCDEF
0-2+1-1+3-1
此时E->B 都转换成小写就是bbb

当有三个rotor时,第一个转完一圈第二个转一个,第二个转完一圈第三个转一个
因此对测试数据

6

BADFEC

ABCDEF

ABCDEF

1

ACE


ABCDEF
+1-1+3-10-2
000000
000000
解的时候反过来从最后一个rotor开始 :A+0->A+0->A+1=B,rotor1旋转 ,C+0->C+0->C-1=B,rotor1旋转,E+0->E+0->E+3=B

有多组 Enigma 输出时除第一组数据不能有空行,其他组之间有空行
下面代码的核心部分也就是4-17行
//transform 用于得到密文到明文的转换关系 按照字典顺序从小到大
//riddle  使用rotor对应的解密表


#include <stdio.h>
#include <string.h>
#include <ctype.h>
void transform(char r[],int ro[],int m)
{
int i;
for(i = 0;i<m;i++)
{
ro[r[i]-'A'] = ('A'+i)-r[i];
}
}
char riddle (char code,int rotor[],int m,int index)
{
int i = code-'A'-index <0? (m+(code-'A'-index)):code-'A'-index;//例如密文B的转换关系在 rotor[1-index]
int x = rotor[i]+code-'A'<0?(m+(rotor[i]+code-'A')):rotor[i]+code-'A';
return x%m+'A';
}
int main(int argc, char *argv[])
{
int index_1,index_2,index_3,m,n,i,cases;
int  rotor_1[26],rotor_2[26],rotor_3[26];
char rotor[26],code;
cases = 0;
while(scanf("%d",&m)&&m!=0)
{
memset(rotor,'\0',sizeof(rotor));
scanf("%s",rotor);
transform(rotor,rotor_1,m);
scanf("%s",rotor);
transform(rotor,rotor_2,m);
scanf("%s",rotor);
transform(rotor,rotor_3,m);
scanf("%d",&n);
getchar();
if(cases++) printf("\n");
printf("Enigma %d:\n",cases);
for(i = 0;i<n;i++)
{
index_1 = index_2 = index_3 = 0;
while(scanf("%c",&code)&&code!='\n')
{
printf("%c",tolower(riddle(riddle(riddle(code,rotor_3,m,index_3),rotor_2,m,index_2),rotor_1,m,index_1)));
index_1++;//偏移量,相对于移动数组
if(index_1==m){index_1 = 0;index_2++;}
if(index_2==m){index_2 = 0;index_3++;}
if(index_3==m) index_3 = 0;
}
printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: