在 ACM 竞赛中,如果 8e18 的 long long 不够用了,又不是特别需要高精度,可以使用 __int128

__int128 的数据范围是 -170141183460469231731687303715884105728 ~ 170141183460469231731687303715884105727 (1e38)。

但是并不是很好用额:

  1. 只能在 64 位环境下使用,32 位是不支持 __int128 的。
  2. Visual Studio 2017 不支持,GCC支持。
  3. 不能使用 scanf/cinprintf/cout 输出。一个解决方案是,可以把转化为字符输出,即 ACM/OI 常提到的快速读入输出。
1
2
3
4
5
6
7
8
9
10
11
12
inline __int128 read()
{
int k=0;
char f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())
if(c=='-')
f=-1;
for(;isdigit(c);c=getchar())
k=k*10+c-'0';
return k*f;
}
1
2
3
4
5
6
7
8
9
10
void print(__int128 x)
{
if(x < 0)
{
x = -x;
putchar('-');
}
if(x > 9) print(x/10);
putchar(x%10 + '0');
}

注意后面的 print 函数其实是不能输出 __int128 的最小值 -170141183460469231731687303715884105728 的,因为它是把负数取反后输出的,而补码系统里面,负数本身就比正数多一个数。不过平时影响不大,毕竟用不到这个数。