您的位置:首页 > 其它

模拟问题之密码学

2016-02-13 18:02 344 查看
许多信息加密过程有着复杂的数学原理,但是一些简单的密码问题通过模拟即可解决。

POJ 3749 破译密码

http://poj.org/problem?id=3749

模运算模拟即可

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char str[205],s[20];

int main()
{
while(~scanf("%s",s)){
if(strcmp(s,"ENDOFINPUT")==0) break;
getchar();
gets(str);
int len=strlen(str);
for(int i=0;i<len;i++){
if(str[i]<91&&str[i]>=65){
str[i]=(str[i]-65-5+26)%26+65;
}
}
scanf("%s",s);
printf("%s\n",str);
}
return 0;
}


UESTC_old - 1063
 易位法字符串加密

密码学是一门既古老又年轻的学科。说它古老,是因为早在几千年前,人类就已经有了通信保密的思想,并先后出现了易位法和置换法等加密方法。到了1949 年,信息论的创始人香农(C.E.Shannon)论证了由传统的加密方法所获得的密文,几乎是都可攻破的,这使得密码学的研究面临着严重的危机。

    直 至进入20世纪60年代,由于电子技术和计算机技术的迅速发展,以及结构代数、可计算性理论学科研究成果的出现,才使密码学的研究走出困境而进入了一个新 的发展时期;特别是美国的数据加密标准DES和公开密钥密码体制的推出,又为密码学的广泛应用奠定了坚实的基础。

    虽然加密方法很多,但最 基本的加密方法只有两种,即易位法和置换法,其它方法大多是基于这两种方法形成的。易位法是按照一定的规则,重新安排明文中的比特或字符的顺序来形成密 文,而字符本身保持不变。按易位单位的不同又可分成比特易位和字符易位两种易位方式。前者的实现方法简单易行,并可用硬件实现,主要用于数字通信中;而后 者即字符易位法则是利用密钥对明文进行易位后形成密文。

    具体方法是:假定有一密钥DCAB,其长度为4,字符串为I love China,去掉空格,四位四位分组,不足四位时用e补齐。具体见下图所示。输出时转化为大写输出。注意分组时要求先去掉空格,取列时按密钥的ASCII 码从小到大取,输出时要求英文字母全转换为大写



复制字符串时注意空格问题
处理字符串到数组时也要注意空格问题

(下面的代码不知道能不能行,OJ上居然没找到这题)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1005;
struct node{
char val;
char str
;
int dth;
}key[25];
int cmp(node a,node b){
return a.val<b.val;
}
char s
;
char upper(char a){
if(a>=97) a-=32;
return a;
}
int main()
{
//freopen("cin.txt","r",stdin);
char code[25];
while(~scanf("%s",code)){
int len=strlen(code);
for(int i=0;i<len;i++){
key[i].val=code[i];
key[i].dth=0;
}
getchar();
gets(s);
int length=strlen(s);
int dex=0;
for(int i=0;i<length;i++){
if(s[i]==' ') continue;
key[dex%len].str[key[dex%len].dth++]=s[i];
dex++;
}
int L=len*key[0].dth;
for(int i=dex;i<L;i++){
key[i%len].str[key[i%len].dth++]='e';
}
/*for(int i=0;i<len;i++){
for(int j=0;j<key[i].dth;j++) printf("%c",key[i].str[j]);
cout<<endl;
}*/
sort(key,key+len,cmp);
for(int i=0;i<len;i++){
for(int j=0;j<key[0].dth;j++) printf("%c",upper(key[i].str[j]));
}
puts("");
}
return 0;
}


POJ 1107 W's Cipher

http://poj.org/problem?id=1107

大意:信息加密过程,不同的字符分成三组,每一组字符向左移动ki次。现在给出k1,k2,k3,给出密文,求出明文。
分析:右移解码,直接模拟。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=100;
char str
;
int vis
;
char s1
,s2
,s3
;
char g1
,g2
,g3
;
int main()
{
//freopen("cin.txt","r",stdin);
int k1,k2,k3;
int top1,top2,top3;
while(scanf("%d%d%d",&k1,&k2,&k3)&&(k1+k2+k3)){
getchar();
gets(str+1);
memset(vis,0,sizeof(vis));
top1=top2=top3=0;
int len=strlen(str+1);
for(int i=1;i<=len;i++){
if(str[i]<='i'&&str[i]>='a'){
s1[top1++]=str[i];
vis[i]=1;
}
else if(str[i]<='r'&&str[i]>='j'){
s2[top2++]=str[i];
vis[i]=2;
}
else {
s3[top3++]=str[i];
vis[i]=3;
}
}
for(int i=0;i<top1;i++){
int dex=i;
dex=(dex+k1)%top1;
g1[dex]=s1[i];
}
for(int i=0;i<top2;i++){
int dex=i;
dex=(dex+k2)%top2;
g2[dex]=s2[i];
}
for(int i=0;i<top3;i++){
int dex=i;
dex=(dex+k3)%top3;
g3[dex]=s3[i];
}
int i1=0,i2=0,i3=0;
for(int i=1;i<=len;i++){
if(vis[i]==1){
printf("%c",g1[i1++]);
}
else if(vis[i]==2){
printf("%c",g2[i2++]);
}
else {
printf("%c",g3[i3++]);
}
}
printf("\n");
}
return 0;
}


POJ 2159 Ancient Cipher

http://poj.org/problem?id=2159

大意:明文经过替换和重新排列得到密文。现在给出明文和密文,求解他们是否是有转化关系。
分析:这题不是模拟题,算是侦探题,哈哈哈。明文经过上诉过程加密后各个字符的个数一定等于原文各个字符的个数。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=105;
char s1
,s2
;
int c1[30],c2[30];
int main()
{
//freopen("cin.txt","r",stdin);
while(~scanf("%s",s1)){
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
scanf("%s",s2);
int len=strlen(s1);
for(int i=0;i<len;i++){
int dex=s1[i]-'A';
c1[dex]++;
}
for(int i=0;i<len;i++){
int dex=s2[i]-'A';
c2[dex]++;
}
sort(c1,c1+30);
sort(c2,c2+30);
bool OK=1;
for(int i=0;i<30;i++){
if(c1[i]!=c2[i]) {
OK=0;
break;
}
}
if(OK) printf("YES\n");
else printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: