高精度大家都认识吧?
但是,高精度这货是真滴长……
于是,人们又发明出了一个东西 __\(int128\)!
__\(int128\)(注意前面有\(2\)个下划线)嘛,把特点写脸上了:占用\(128\)位,也就是\(16\)个字节。储存范围,自然也是占用\(64\)位的\(long\) \(long\)的\(2\)倍。换算一下,能存三十多近四十位。基本上可以代替部分高精度了。
那__\(int128\)这么\(NB\),咋就不能被广泛使用呢(好多教材没教这个对不)?
因为它缺陷也很多:
- 不通用。__\(int128\)并没有在任何一个\(C\)艹标准中严格定义 ,所以目前它只是\(GCC\)系列编译器的专属(\(NOI\) \(Linux\)恰好也用的是\(GCC\),所以__\(int128\)可用。然鹅,使用\(Visual\) \(Studio\)的同志们,你们用的编译器一般是\(MSVC\),是不支持的)。目前测试,只在\(Linux\)系统下能够正常使用(好在大部分地区比赛、评测均已切换至\(NOI\) \(Linux\) \(2.0\)了)。
- 不方便。__\({int128}\)目前看来是不支持直接读入、输出的。管你是\(cin\)、\(cout\)、\(scanf\)还是\(printf\),都甭想输入一个__\(int128\)类型的数据。于是它输入得用\(sring\)输入字符后\(\times 10 +\)尾数,输出得数位分解。
- 空间大,速度慢。 __\(int128\)占用了\(16\)个字节来存,\(MLE\)的风险显著增加。空间大速度还慢。你想啊,人家\(int\)才\(32\)位,\(64\)位的\(CPU\)一次处理俩;你\(128\)位,\(64\)位的\(CPU\)两次处理\(1\)个,不得慢死(\(TLE\)风险增加)……
不过,为了让大家多掌握(pian)亿点东(fen)西,下面给出使用__\(int128\)时的基本框架。
#include <bits/stdc++.h>
#define log printf
using namespace std;
__int128 n;
__int128 reader() {
__int128 x = 0; // 虽然限制那么多,但咱赋个值总还是可以的吧……
int w = 0;
char ch;
while (!isdigit(ch)) {
w |= ch == '-'; ch = getchar();
}
while (isdigit(ch))
x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
void output(__int128 x) {
if (x < 0) {
putchar('-');
x *= -1;
}
if (x > 9)
output(x / 10);
putchar(x % 10 + '0'); // 众所周知这货只能搞四则运算,输出还请数位分解一下(其实就是快读快写)
}
int main() { // 你变量全用__int128我也不拦着你,但永远记住main函数不开int(好吧用signed也行)会CE的哈
n = reader();
// 请自行操作
output(n);
return 0;
}
说了这么半天慢的太吓人的__\(int128\),那有木有一个特快的,比如说\(16\)位\(2\)个字节的哪种?
还真有,而且这个槽点就没那么多了。它就是——\(short\)!
\(short\)这玩意儿可比__\(int128\)强多了。它是通用的,也是可以直接读入、输出的(\(scanf\)和\(printf\)统一用“%hd”)。
那为啥它用的也不多呢?
因为它太省内存了,你说它就\(2^{15} - 1\)(不到\(4\)万)的存储范围能存个啥?