Klee's SUPER DUPER LARGE Array!!!
每次測試時間限制:2秒
每次測試的記憶體限制:256 MB
題目描述
Klee 擁有一個長度為 n 的陣列 a,陣列中的元素依次為 [k, k + 1,..., k + n - 1]。Klee 希望選擇一個索引 i(1≤i≤n),使得 x = |a1 + a2 + ⋯ + ai - ai+1 - ⋯ - an| 最小。其中對於任意整數 z,|z| 表示 z 的絕對值。要求輸出 x 的最小值。
輸入格式
第一行包含 \(t\) ( \(1 \leq t \leq 10^4\) )—測試用例的數量。
每個測試用例包含兩個整數 \(n\) 和 \(k\) ( \(2 \leq n, k \leq 10^9\) )—陣列的長度和陣列的起始元素。
輸出格式
對於每個測試用例,在新的一行上輸出 \(x\) 的最小值。
樣例 #1
樣例輸入 #1
4
2 2
7 2
5 3
1000000000 1000000000
樣例輸出 #1
1
5
1
347369930
提示
注意
在第一個示例中, \(a = [2, 3]\) 。當選擇 \(i = 1\) 時, \(x = |2-3| = 1\) 。可以看出,這是 \(x\) 的最小可能值。
在第三個樣本中, \(a = [3, 4, 5, 6, 7]\) 。當選擇 \(i = 3\) 時, \(x = |3 + 4 + 5 - 6 - 7| = 1\) 。可以看出,這是 \(x\) 的最小可能值。
題解
注意到本題中,最後一個樣例過大,而題設的陣列是公差為1的等差數列,很容易想到,等差數列求和公式。(死去的高中知識怎麼在攻擊我??)
\[S_n = \frac{n(a_1 + a_n)}{2} ~~~~~ 或者 ~~~~~ S_n = \frac{n[2a_1 + (n-1)d]}{2}
\]
#include <iostream>
using namespace std;
long long n, l, r, mid;
int main() {
int t;
scanf("%d", &t);
while (t--) {
long long k;
scanf("%d%lld", &n, &k);
l = 0; r = n;
long long ans = 0;
for (int i = 1; i < n; i++) {
}
ans =10 * (n+k);
while (l <= r) {
mid = (l + r) >> 1;
long long sum = 0; int num = 0;
int nn = n;
long long add = 0, sub = 0;
//等差數列求和;死去的記憶正在攻擊我
add = mid * (2 * k + mid - 1) / 2;
sub = (n - mid)*(2 * k + n + mid - 1) / 2;
sum = add - sub;
long long sum1 = abs(sum);
if (sum1 <= ans) ans = sum1;
if (sum > 0) r = mid - 1;
else l = mid + 1;
}
printf("%d\n", ans);
}
return 0;
}