n 個小孩排成隊,編號 1..n。第 i 個小孩手持數字 i(i+1)(i+2)。第 k 個小孩需報出前 k 個數字之和。求第 n 個小孩報出的數值模 9999。
n ≤ 10¹⁰⁰ (超大整數,以字串輸入)。
單項:f(i) = i(i+1)(i+2) = i³ + 3i² + 2i
前 n 項和:
S(n) = Σ f(i) = Σi³ + 3Σi² + 2Σi
代入求和公式:
Σi = n(n+1)/2Σi² = n(n+1)(2n+1)/6Σi³ = [n(n+1)/2]²化簡得驚人簡潔公式:
S(n) = n(n+1)(n+2)(n+3) / 4
因 n 極大 (10¹⁰⁰),需以字串處理。利用模運算性質:
(a × b) mod m = [(a mod m) × (b mod m)] mod m
但分母 4 需處理模逆元。因 mod = 9999 = 9 × 11 × 101,4 與 9999 不互質,**無模逆元**。
計算 X = n(n+1)(n+2)(n+3) mod (4 × 9999 = 39996),然後 S = X / 4 (整除)。
證明:n(n+1)(n+2)(n+3) 為 4 連續整數乘積,**必能被 4 整除**。設真值為 4k。
X = 4k mod 39996 = 4k - 39996×q = 4(k - 9999q) → X 為 4 的倍數。
X/4 = k - 9999q ≡ k (mod 9999) ✓
#include
using namespace std;
const int MOD = 9999;
const int BIG_MOD = 4 * MOD; // 39996
// 字串轉模值
int strMod(const string& s, int mod) {
long long res = 0;
for (char c : s) {
res = (res * 10 + (c - '0')) % mod;
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string n_str;
while (cin >> n_str) {
long long n_mod = strMod(n_str, BIG_MOD);
// 計算 n, n+1, n+2, n+3 模 BIG_MOD
long long a = n_mod;
long long b = (n_mod + 1) % BIG_MOD;
long long c = (n_mod + 2) % BIG_MOD;
long long d = (n_mod + 3) % BIG_MOD;
long long prod = a;
prod = (prod * b) % BIG_MOD;
prod = (prod * c) % BIG_MOD;
prod = (prod * d) % BIG_MOD;
int ans = (prod / 4) % MOD;
cout << ans << '\n';
}
return 0;
}
(res*10 + digit) % mod。延伸思考:若模數為質數
p,分母d不被p整除,可用費馬小定理求模逆元d^(p-2) mod p。本題因模數合數且分母 4 與模數不互質,擴大模數法更通用、優雅。