前言

以前的加密都是映射关系,只要得到了表格就好了。

鸣谢: @ 提出错字。

无聊的说明

这是某个时间想到的(可能是在集训或者上课的时候吧,只有这两个时间最无聊)。

对要加密的字符的 ASCII 调整会怎么样?

其实一开始想的是交换位数,但是很多字符会神秘消失。因为 ASCII 有的是一位数,有的是三位数,不好调整。

于是就想到了格雷码 。其实我还没学这个,但是从 DP 了解到,计算 x 的格雷码的方法是 x ^ (x >> 1)

于是就开始写代码了(此处为伪代码):

while get(c):
    c = c ^ (c >> 1);
    put(c);

但是这有一些问题: ASCII 有些字符看不见 ,也打不出来。这些是要跳过的字符。

我整理了一些空的字符,在代码的 wit 函数里了。可以看到的空格也是要跳过的。

所以有了下面的伪代码:

while get(c):
    c = c ^ (c >> 1);
    while !check(c):
        c = c ^ (c >> 1);
    put(c);

但是我希望保留空格。但是这里还是有问题:如果要加密一句话,每个字符 Gary 的次数不同,所以无法解码。

根据我发现的性质:每个字符编码一定次数后都会返回到原字符。 所以才有了上面的一条问题。如果一个句子每个字符编码次数不同,就不能编码多次后解码。

所以,每次检查句子,如果有一个字符空,那么就再给每个字符都编码一次。就是下面的代码了。


#include <iostream>
using namespace std;

bool wit(char c)
{
	return (c <= 32 || c == 127);
}

bool cse(string s)
{
	for (char ch : s)
	{
		if (ch == ' ')continue;
		if (wit(ch))return 0;
	}
	return 1;
}

string gary(string s)
{
	for (char& ch : s)
	{
		if (ch == ' ')continue;
		ch = ch ^ (ch >> 1);
	}
	return s;
}

int main()
{
	string s;
	while ((getline(cin, s)))
	{
		s = gary(s);
		while (!cse(s))
		{
			s = gary(s);
		}
		cout << s << "\n";
	}
    return 0;
}