T2
场上打暴力直接拿到 15,各种胡乱优化后仍只有 20,出考场被同学告知去重就能 A,我那死去的脑细胞啊……
可恶的诈骗题。
有序列 \(a\),一共 \(n\) 个元素。有 \(q\) 次询问,对于每次询问 \(i\)(\(1 \le i \le q\)),需要输出 \(a_1+i,a_2+i,\ldots,a_n+i\) 的最大公因数,即 \(\gcd (a_1+i,a_2+i,\ldots,a_n+i)\)。对于 \(k\) 个数,若 \(k \ge 3\),\(\gcd (c_1,c_2,\ldots,c_k)\) 就是 \(\gcd (\gcd(c_1,c_2,\ldots,c_{k-1}),c_k)\)。
Part 1
我会暴力!
直接按题意模拟,先用一个数组 \(b\) 来存储,\(b_i\) 表示 \(a_i+i\) 的值。然后分两种情况,若 \(n \le 2\),直接输出 \(\gcd(b_1,b_2)\);从 \(1\) 遍历到 \(n-1\),用 \(ans\) 存当前的最大公因数,在 \(ans\) 与 \(b_n\) 之间求最大公因数。
可拿 \(15\) 分,代码不放。
Part 2
我会优化!
首先,一旦 \(ans\) 变成 \(1\) 了,那就不用再看了,最大公因数必然为 \(1\),直接 break 掉,再加个特判。优化后可拿 \(17.5\) 分。
然后,注意到我存储 \(b_i\) 要从 \(1\) 到 \(n\) 遍历,非常慢,不如直接在更新 \(ans\) 时先求 \(b_i\) 的值,在与 \(b_i\) 取最大公因数。优化后可拿 \(20\) 分。
于是这个蒟蒻觉得优化光了,开始推规律,结果一无所获,脑细胞全死光了……
呜呜呜,出了考场某大佬告诉我可以去重!对啊!
对于于所有测试点,保证 \(1 \le n \le 10^5\), \(1 \le q \le 10^5\),\(1 \le a_i \le 1000\)!
因为有 \(n\) 个 \(a_i\),既然 \(1 \le n \le 10^5\),但 \(a_i\) 的最大值 \(1000\) 比 \(10^5\) 小,说明有重复的!
而且每次 \(a_i\) 加的 \(i\) 是相同的,所以 \(a_i\) 的顺序不重要,于是直接用 set 去重即可。
Code
#include <bits/stdc++.h>
#define qwq(i,a,b) for(int i=(a);i<=(b);++i)
#define qaq(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
const int N = 1e5 + 5;
int n, q;
int b[N];
int ans;
int main()
{
cin >> n >> q;
set<int> st;
qwq (i, 1, n) {
int x;
cin >> x;
st.insert(x);
}
vector<int> a;
for (auto it : st) {
a.push_back(it);
}
int l = a.size();
if (l <= 2) {
qwq (i, 1, q) {
b[1] = a[0] + i;
b[2] = a[1] + i;
cout << __gcd(b[1], b[2]) << '\n';
}
}
qwq (i, 1, q) {
bool f = 0;
b[1] = a[0] + i;
ans = b[1];
qwq (j, 2, l - 1) {
b[j] = a[j - 1] + i;
ans = __gcd(ans, b[j]);
if (ans == 1) {
f = 1;
break;
}
}
if (f == 1) {
cout << "1\n";
} else {
b[l] = a[l - 1] + i;
ans = __gcd(ans, b[l]);
cout << ans << '\n';
}
}
}

浙公网安备 33010602011771号