题解 P1079 【Vigenère 密码】

· · 题解

我来发个代码稍短一点的题解。

铺垫一个关于ASCII码的小知识:字母'A'的ASCII码是41H(0100 0001B),字母'a'的ASCII码是61H(0110 0001B),字母'A'与'a'的二进制后5位是相同的,所以无论是大写字母还是小写字母x,x &31(1 1111B)的值就是x在字母表里的顺序。

开始题解:本题的目的就是问你如何去篡位,例如秘钥k里面的字符'C'代表的就是明文向后篡2位得到密文,反过来已知密文,'C'代表的就是向前篡2位,这样'Y'就得到了'W'。

而篡位是有边界的,就是如果篡过了头,需要再回来,A之后就是Z了。所以需要判断一下密文的和篡位之间的大小,如果篡位大,需要补26.

参考代码:

#include <iostream>
using namespace std;
int main() {
    string k,c;
    cin>>k>>c;
    for (int i=0;i<c.length();i++) {
        int t=(k[i%k.length()]&31)-1;
        c[i]=(c[i]&31)-t>0?c[i]-t:c[i]-t+26;
    }
    cout<<c<<endl;
    return 0;
}