http://icpc.upc.edu.cn/problem.php?cid=1683&pid=0
观察运算®的规则表格发现该表格是左下和右上对称的,也就是说:可以认为加密时行标题是明文、列标题是密钥;也可以认为加密时行标题是密钥,列标题是明文。这里我们把行标题看做明文,列标题看做密钥。
然后还可以发现:加解密运算规则表格的每一列其实是把行标题加上一个对应值就可以转换出来的。例如:表格中的第0列(即密钥为A的那一列)是把行标题各字母分别加0转换而来;表格中的第1列(密钥为B的那一列)是把行标题各字母分别加1转换而来;……以此类推,我们可以发现一个规律:
明文字母 = (密文字母-A - (密钥字母 - A) + 26 ) mod 26 + A
上面公式里面加或减A是为了求得对应的密文字母或密钥字母在26个英文字母表当中的序号(0~25),所以需要讨论密文字母和密钥字母的大小写然后再决定是减去(或加上)大写A或小写a。具体的讨论可以看代码。
#include <cstdio>
using namespace std;
char c1[102],c[1002],c2;
int i,j;
int main()
{
scanf("%s",c1);
getchar();
scanf("%s",c);
for(;c[j]!='\0';j++)
{
if(c[j]>='A'&&c[j]<='Z')
{
if(c1[i]>='A'&&c1[i]<='Z')
c2=(c[j]-'A'-(c1[i]-'A')+26)%26+'A';
else c2=(c[j]-'A'-(c1[i]-'a')+26)%26+'A';
}
else
{
if(c1[i]>='A'&&c1[i]<='Z')
c2=(c[j]-'a'-(c1[i]-'A')+26)%26+'a';
else c2=(c[j]-'a'-(c1[i]-'a')+26)%26+'a';
}
printf("%c",c2);
i++;
if(c1[i]=='\0') i=0;
}
printf("\n");
}