【题解】【NOIP2012】Vigenère 密码 ←2013.8.1日作业

题目描述

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

记为 k  Vigenère 密码中,密钥 是一个字母串,k=k1k2kn。当明文 M=m1m2m时,得到的密文 C=c1c2cn,其中 ci=mi®ki,运算®的规则如下表所示

 

输入

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

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

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

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

明文 

密钥 

密文 

输入文件名为 vigenere.in 

输入共 行。 

第一行为一个字符串,表示密钥 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; 
} 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值