题目描述


16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法——Vigenère 密码。Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为南军所广泛使用。  在密码学中,我们称需要加密的信息为明文,用 M 表示;称加密后的信息为密文,用 C 表示;而密钥是一种参数,是将明文转换为密文或将密文转换为明文的算法中输入的数据,

记为 k。 在 Vigenère 密码中,密钥 k 是一个字母串,k=k1k2…kn。当明文 M=m1m2…mn 时,得到的密文 C=c1c2…cn,其中 ci=mi®ki,运算®的规则如下表所示

 


输入

Vigenère 加密在操作时需要注意: 

1. ®运算忽略参与运算的字母的大小写,并保持字母在明文 M 中的大小写形式; 

2. 当明文 M 的长度大于密钥 k 的长度时,将密钥 k 重复使用。 

例如,明文 M=Helloworld,密钥 k=abc 时,密文 C=Hfnlpyosnd。

明文 

密钥 

密文 

输入文件名为 vigenere.in。 

输入共 2 行。 

第一行为一个字符串,表示密钥 k,长度不超过 100,其中仅包含大小写字母。第二行

为一个字符串,表示经加密后的密文,长度不超过 1000,其中仅包含大小写字母。


输出


输出共 1 行,一个字符串,表示输入密钥和密文所对应的明文。


样例输入

ComleteVictory  
Yvqgpxaimmklongnzfwpvxmniytm


样例输出


Wherethereisawillthereisaway


*********************************************************


顿时觉得只可意会不可言传……


从题目的描述来看,从明文转为密文的方式就是那一张表,假设表为一张坐标图,则有横轴与纵轴之分,把明文作为横轴,密钥作为纵轴(反着也行),给出了密钥和密文,将密钥和明文的字母对上去,找到的字母就是当前明文中字母的密文。


接下来为找规律


我理解的规律为:密文字母=明文字母+(密钥字母在字母表中的标号-1)


假设H为明文字母,a为密钥,则H+(1-1)=H


假设e为明文字母,b为密钥,则e+(2-1)=f


因为在解码表中,横轴与纵轴均为递增顺序,设明文不变,密钥的ascii码越大,密文ascii码也越大,而密钥增长多少,密文也就增长多少。


【注意】此仅为明文化为密文的规律,而题目是给密文求明文,所以规律要反过来:明文字母=密文字母-(密钥字母在字母表中的编号-1)。


因为密文和明文的大小写必须一致,所以鄙人采取了判断一个输出一个的方法


将密钥化为数字,即密钥在字母表中的编号-1


然后再用密文去减(鄙人在此处耗费了不少时间,要是密文减密钥的数字小于了字母a,就要取两者差的绝对值再用z去减,大写也一样,反正得考虑)。


减好了的数字就可以输出来了


题解至此完,下面一栏为代码(为了完整一点还是贴上来)


*********************************************************



#include<iostream> 
#include<cstring> 
#include<cstdio> 
#include<fstream> 
#define MAXN 1100 
#define MAXK 110 
using namespace std; 
char yue[MAXK],miwen[MAXN]; //密钥,密文
int main() 
{ 
    //freopen("vigenere.in","r",stdin); 
    //freopen("vigenere.out","w",stdout); 
    scanf("%s",yue); 
    scanf("%s",miwen); 
    int a; 
    int l=strlen(yue); //密钥长度
    int ll=strlen(miwen); //密文长度
    for(int i=0;i<ll;i++) 
    { 
        char x=yue[i%l]; //当前要使用的密钥字母
        if(miwen[i]>='a'&&x<='Z')x+=32; //使密钥和密文的大小写一致
        if(miwen[i]<='Z'&&x>='a')x-=32; //同上(些许麻烦可改进)
        if(x>='a') a=x-'a'; 
        else a=x-'A'; //密钥在字母表中的编号-1
        int j=miwen[i]-x; //是否不够减
        if(j<0&&miwen[i]>='a')miwen[i]='z'+j+1;//是否不够减 
        else if(j<0&&miwen[i]>='A') miwen[i]='Z'+j+1; //是否不够减
        else miwen[i]-=a; 
        cout<<miwen[i]; 
    } 
    return 0; 
}