信息学奥赛一本通:1402:Vigenère密码

1402:Vigenère密码


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 17245     通过数: 9250 

【题目描述】

6世纪法国外交家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。

【输入】

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

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

对于100%的数据,输入的密钥的长度不超过100,输入的密文的长度不超过1000,且都仅包含英文字母。

【输出】

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

【输入样例】

CompleteVictory
Yvqgpxaimmklongnzfwpvxmniytm

【输出样例】

Wherethereisawillthereisaway

密文=密钥+原文-a;(前面相加大于z时,减z再减1,不减a了)

原文=密文-密钥+a;(前面相减小于0时,加上z再加上1,不加a)

#include<iostream>
#include<cmath> 
#include<cstring>
char a[105],b[1505];

using namespace std;
int main()
{
int i=0,j,n,k=0,m=0,t=0;
    scanf("%s",a);
    scanf("%s",b);
    m=strlen(a);//取长度,然后转换为小写字符
    for(i=0;i<m;i++)
    {
    	if(a[i]>='A'&&a[i]<='Z')
    	a[i]=a[i]+'a'-'A';
	}
    n=strlen(b);//取密码长度,然后换成明文
    for(i=0;i<n;i++)
    {
    	if(b[i]>='A'&&b[i]<='Z')//大写时,因为还要照大写输出
    	{
    		if((b[i]+'a'-'A'-a[i%m])<0)//i%m是密钥循环使用,m是密钥长度
    		 b[i]='z'-a[i%m]+b[i]+1;//看表中是,把列看作密钥的话,行是明文,行加列(都从0开始)加a,(超过z的减z,再减1)那样,密文-密钥就有可能是负值,就需要+z+1;
	         else
	         b[i]=b[i]-a[i%m]+'a';}
		else//小写时
	{
		if(( b[i]-a[i%m])<0)
		 b[i]='z'+b[i]-a[i%m]+1;
		 else
		 b[i]=b[i]+'a'-a[i%m];
		}
		
	}
    	 	printf("%s",b); return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值