Caesar解密-number theroy

原题如下所述:

 1.  It is known that the following crypted paragraph is encryted using a slighted enhanced Caesar encryption method of the form f(p)=(ap+b)mod29.
 
         jgc!.chr, dhdw,nbn bn kdncy oh uxc jdru uxdul bh dh, qbfch nugcurx oj mgbuuch wdhq.dqcl rcgudbh wcuucgn dhy roakbhdubohn oj wcuucgn orr.g mbuxfdg,bhq jgc!.chrbcns aogcofcgl uxcgc bn d rxdgdrubnubr ybnugbk.uboh oj wcuucgn uxdu bn go.qxw, uxc ndac jog dwaonu dww ndavwcn oj uxdu wdhq.dqcs
 
  What is also known is the two most frequently used letters in the paragraph are t and e.The reference alphabet is an array of length 29 "abcdefghijklmnopqrstuvwxyz,.!", indicating that space is not handled during encryption (space remains space). Try to de-cypher the message and give the plaintext.


解密程序:

// Caesar.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <IOSTREAM>
#include <STRING>

using namespace std;

const string codes("jgc!.chr, dhdw,nbn bn kdncy oh uxc jdru uxdul bh dh, qbfch nugcurx oj mgbuuch wdhq.dqcl rcgudbh wcuucgn dhy roakbhdubohn oj wcuucgn orr.g mbuxfdg,bhq jgc!.chrbcns aogcofcgl uxcgc bn d rxdgdrubnubr ybnugbk.uboh oj wcuucgn uxdu bn go.qxw, uxc ndac jog dwaonu dww ndavwcn oj uxdu wdhq.dqcs");

//字符串处理 把字符串中所有,.!符号分别替换为{|} 
//方便处理
string convert2unalpha(const string &str0)
{
	string str = str0;
	size_t pos ;
	while((pos =str.find(',',0))!=string::npos)
		str.replace(pos,1,1,'{');
	while((pos =str.find('.',0))!=string::npos)
		str.replace(pos,1,1,'|');
	while((pos =str.find('!',0))!=string::npos)
		str.replace(pos,1,1,'}');
	return str;
}

//字符串处理 把字符串中所有{|}符号分别替换为,.! 
//还原字符串
string convert2alpha(string &str0)
{
	string str = str0;
	size_t pos;
	while((pos =str.find('{',0))!=string::npos)
		str.replace(pos,1,1,',');
	while((pos =str.find('|',0))!=string::npos)
		str.replace(pos,1,1,'.');
	while((pos =str.find('}',0))!=string::npos)
		str.replace(pos,1,1,'!');
	return str;
}

//获取字符串中出现频率最高的2个字符
//保存它们相对于'a'的偏移量
void max_nums_char(string source,int &fm,int &sm)
{
	int arr[29];
	memset(arr,0,sizeof(int)*29);
	int first_max=0,second_max=0;
	for(;!source.empty();source = source.substr(1))
	{//统计每个字符出现次数
		if(source.at(0) != ' ')
			arr[source.at(0)-'a']++;
	}

	for(int i = 0;i<29;i++)
	{//找出具有最大出现次数的字符所在表项的索引
		if(arr[i]>arr[first_max])
		{
			second_max = first_max;
			first_max = i;
		}
	}
	fm = first_max;
	sm = second_max;
}

//根据获得的最高频率的字符计算解密参数a b的值
//根据题意 应能够在-29~+29范围内计算出合适的a b 值
//如果求不出合适的结果 那么返回false
bool get_ab(int fm,int sm,int &a,int &b)
{//	19 + 29k = fm*a + b
//	4  + 29K = sm*a + b
	double d_a,d_b;
	double dist = fm -sm;
	for(int k=-dist;k<=dist;k++)
	{//在-29~+29范围内求解能满足方程组的整数a
		d_a = (15 + 29 * k)*1.0 / dist;
		if(d_a ==(int)d_a)
			break;
	}
	if(d_a !=(int)d_a)
			return false;
	a = d_a;
	if(a<=0)
		for(int k1=fm*a;k1<=-fm*a;k1++)
		{//在-29~+29范围内求解能满足方程组的整数b
			d_b = (19+29*k1)*1.0 / (28*a);
			if(d_b ==(int)d_b)
				break;
		}
	else
		for(int k1=-fm*a;k1<=fm*a;k1++)
		{//在-29~+29范围内求解能满足方程组的整数b
			d_b = (19+29*k1)*1.0 / (28*a);
			if(d_b ==(int)d_b)
				break;
		}
	if(d_b !=(int)d_b)
		return false;
	b = d_b;
	return true;
}

void eval(string &source,string &decode,int a,int b)
{//根据式f(p)=(ap+b)mod29 及解密参数a b ,对加密字符串进行解密
	decode = "";
	for(string::iterator iter0=source.begin();iter0!=source.end();iter0++)
	{
		if(*iter0 == ' ')
		{//保留空格
			decode.append(1,' ');
			continue;
		}
		int p = *iter0 - 'a';
		int res = (a * p + b) % 29 ;
		if(res<0)//处理负数
			res = res + 29;
		//转换成字符,追加到字符串
		decode.append(1,res + 'a');
	}
	
}

int main(int argc, char* argv[])
{
	string regular_codes;
	string result;
	int fm,sm;
	int a,b;
	
	//将原始密文中的,.!转换为ascii紧挨着abc...xyz的{|}字符
	//方便后续处理
	regular_codes = convert2unalpha(codes);

	//统计密文中出现频率最高的字符
	max_nums_char(regular_codes,fm,sm);
	cout << "最大频率字符:"<<(char)(fm+'a')<<",第二最大频率字符:"<<(char)(sm+'a')<<endl;

	//根据给出的条件及最高频率字符求解解密参数a b
	if(!get_ab(fm,sm,a,b))
	{
		perror("计算解密参数a b 值发生错误!");
		exit(-1);
	}
	cout << "解密参数a="<<a<<", 解密参数b="<<b <<endl;

	//根据a b 值进行译码
	eval(regular_codes,result,a,b);
	
	//处理完毕
	//转换为常规字符串
	result = convert2alpha(result);
	cout <<"解密结果"<<endl;
	cout << result <<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanzhong104204

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值