給定 N ≤ 10000 個正整數(每個 ≤ 15000),選出非空子集使其和為 N 的倍數。保證有解。
考慮前綴和 S[i] = a[0] + ... + a[i] (0 ≤ i < N)。共 N 個前綴和,對 N 取模餘數只能是 0..N-1(共 N 種)。
S[i] % N == 0,則 [0..i] 即為答案N 個餘數落入 N-1 個非零抽屜,必有 S[j] % N == S[i] % N (j > i),則 (S[j] - S[i]) % N == 0,即 [i+1..j] 和為 N 的倍數mod[r] = imod[r] != -1,輸出 [mod[r]+1 .. i][0 .. i]
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 10010;
int a[MAXN], mod[MAXN];
long long sum[MAXN];
int main() {
int n;
while (scanf("%d", &n) == 1) {
memset(mod, -1, sizeof(mod));
for (int i=0; i
mod 數組記錄餘數首現位置,O(1) 判斷重複long long 防溢出(10000 × 15000 = 1.5e8 仍在 int 範圍,但習慯用 long long)