题解 P1079 【Vigenère 密码】

学无止境

2018-02-20 19:43:49

Solution

这应该是最短的代码了吧(雾) **规律:答案是密文的ascll减去密钥的ascll再加上A字母的ascll(还原为大写字母)** 我预处理了一下(还原为大写字母),更方便了。 **Code:** ``` #include<bits/stdc++.h> using namespace std; char m[1001],k[101],yclm[1001],yclk[101],ans[1001];//m存的是密文,k是密钥 ,yclm是将m里的密文预处理(全部换为大写),方便解密,yclk一样,ans放答案 int main() { scanf("%s%s",k,m);//读入两个字符串 int l_m=strlen(m),l_k=strlen(k);//计算m(密文)的长度,k(密钥)的长度 for(register int i=0;i<l_m;i++) yclm[i]=toupper(m[i]);//对密文预处理,全部转为大写,存入字符串yclm for(register int i=0;i<l_k;i++) yclk[i]=toupper(k[i]);//对密钥预处理,全部转为大写,存入字符串yclk for(register int i=0;i<l_m;i++)//解密: ans[i]=yclm[i]-yclk[i%l_k]+'A',ans[i]=ans[i]<'A'?ans[i]+26:ans[i];//观察的规律, yclk[i%l_k]是指密钥重复使用,解密的结果就是——密文的ascll减去密钥的ascll再加上A字母的ascll(还原为大写字母),对于密钥ascll>密文ascll的类型,解密后不在大写字母区间内,再处理,将ascll加上26 for(register int i=0;i<l_m;i++)//还原 cout<<(m[i]>='A'&&m[i]<='Z'?ans[i]:(char)tolower(ans[i]));//如果密文中这个字母是大写, 接输出对应答案;否则是小写,那么将对应答案转为小写再输出 return 0; } ``` 再附无注释代码: **Code:** ``` #include<bits/stdc++.h> using namespace std; char m[1001],k[101],yclm[1001],yclk[101],ans[1001]; int main() { scanf("%s%s",k,m); int l_m=strlen(m),l_k=strlen(k); for(register int i=0;i<l_m;i++) yclm[i]=toupper(m[i]); for(register int i=0;i<l_k;i++) yclk[i]=toupper(k[i]); for(register int i=0;i<l_m;i++) ans[i]=yclm[i]-yclk[i%l_k]+'A',ans[i]=ans[i]<'A'?ans[i]+26:ans[i]; for(register int i=0;i<l_m;i++) cout<<(m[i]>='A'&&m[i]<='Z'?ans[i]:(char)tolower(ans[i])); return 0; } ```