使用 ``1ll<<(N-1)`` 将大量值分配给 long long int 变量

using ``1ll<<(N-1)`` to assign a large number of value to a long long int variable

我看到的问题是这样写的:给你一个大小为N的数组A。如果元素 Ai 的值 (Ai) 大于或等于 Ki[=30=,则称该元素带电] 和 Ki 是包含元素 Ai 的数组 A 的子集总数。

逻辑很简单,一个数字作为子集出现的次数是2^N-1次。但在某些测试用例中,N 为 4000+。因此,2^N-1 将超出任何变量类型所能容纳的范围,但在编辑中,作者使用了 1ll<<(N-1)。我知道左移运算符是 X<<Y = X*2^Y。但是这个 1ll 是什么?它是如何存储如此大的价值的?

#include <bits/stdc++.h>

#define M 1000000007

using namespace std;

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int T;
  cin >> T;
  while (T--) {
    int N;
    cin >> N;
    long long arr[N];
    for (int i = 0; i < N; i++)
      cin >> arr[i];
    if (N >= 64)
      cout << 0 << endl;
    else {
      long long val = (1ll << (N - 1));
      long long ans = 0;
      for (int i = 0; i < N; i++)
        if (arr[i] >= val)
          ans = (ans + arr[i] % M) % M;
      cout << ans << endl;
    }
  }
}

1<<N-1 解释了 2^N-1 但是 1ll 是否意味着它可能需要 long long 和 long long val = 1ll<<N-1;意味着它可以达到 128 位?

But what is this 1ll?

1ll 是一个 integer literal1 是一个 十进制文字 ll 是一个 整数后缀 。后缀ll表示整数字面量的类型是long long int1 意味着文字的值是 1.

And how is it able to store such large value?

我想你问的是这条线:

long long val = (1ll << (N - 1));

因为之前的if (N >= 64) .. else,我们知道N < 64。所以最大数量可以是:

1ll << 63 - 1   =
1ll << 62       =
0x4000000000000000

这只是一个适合 long long int 类型的数字。 long long int 类型至少有 64 位。

如果没有 ll 后缀,1 的类型将是 int。在 int 类型比 64 位窄的体系结构上,例如。 16 位,然后会发生未定义的行为。将变量左移一个大于或等于左操作数位长度的数字是未定义的行为,请参见 ex。 this question.

如果你问的是这条线:

ans = (ans + arr[i] % M) % M;

正在计算求和模#define M 1000000007。通常做 assignments/homework 计算和模这个数字,见前 this or this。该算法计算总和模 1000000007,而不是整数,这就是它能够将其存储在 long long 变量中的原因。