压 93/94 位打表
93 位打表介绍
压 \(93\) 位打表就是把要打表的数字转换成 \(93\) 进制, 以此来缩短打表部分的代码长度. 例如打表 int
型数字时, 可以用 \(\lceil\log_{93}{(2^{31}-1)}\rceil=5\) 个字符表示(事实上, int
还有负数, 但是我们遇到的题目要求的结果一般是非负数, 所以不管, 反正也是小问题). 至于为什么是 93 位, 因为 char
类型里有 95 个可见字符, \(ASCII\)码从 \(32\) 到 \(126\), 其中 \
和 "
在字符串表示中会引起错误, 所以我们跳过这两个字符.
打表的时候可以直接把这些字符串拼接在一起, 并在前面加五个空格, 然后以 \(5\) 的倍数访问对应位置.
// 数据生成
char v[6];
char dc(int _n) {
_n += 32;
if (_n >= '"') _n++;
if (_n >= '\\') _n++;
return (char)_n;
}
void wk(int _n) {
inc(i, 0, 4) {
v[4 - i] = dc(_n % 93);
_n /= 93;
}
inc(i, 0, 4) printf("%c", v[i]);
}
//翻译字符
const char s[] = {" 打表内容"};
int dc(char c) {
if (c > '\\') c--;
if (c > '"') c--;
return c - 32;
}
int wk(int _l, int _r) {
int _res = 0;
inc(i, _l, _r) _res = _res * 93 + dc(s[i]);
return _res;
}
但是今天写压 93 位打表的时候遇到了一个问题, 我打表的字符串中有一段 ??=
引起 trigraph
警告, 据大大说是因为我们学校 \(oj\) 用 -std=C++xx
编译, 所以没有关闭 trigraph
. 解决方案: 1. 跳过 ?
, 压 \(92\) 位, 毕竟想用 \(5\) 个字符表示 int
型的数只需要 \(\lceil\sqrt[5]{2^{31}-1}\rceil=74\) 进制; 2. 跟着编译器警告把 ??X
处断开; 3. 使用 \(raw string literal\), 既避免了 \(trigraph\), 还多了个 \
来表示, 变成 \(94\) 位. 最后一种方案个人比较喜欢.
94 位打表代码
// 数据生成
char v[6];
char dc(int _n) {
_n += 32;
if (_n >= '"') _n++;
return (char)_n;
}
void wk(int _n) {
inc(i, 0, 4) {
v[4 - i] = dc(_n % 94);
_n /= 94;
}
inc(i, 0, 4) printf("%c", v[i]);
}
// 翻译字符
const char s[] = R"( 打表内容)";
int dc(char c) {
if (c > '"') c--;
return c - 32;
}
int wk(int _l, int _r) {
int _res = 0;
inc(i, _l, _r) _res = _res * 94 + dc(s[i]);
return _res;
}
大概是这个太简单了, 网上都找不到相关介绍