判断是否为等差数列:先预处理出区间最大、最小值,算出公差,然后根据数学方法求出理论上的数列所有项的和以及数列所有项的平方和,与真实值对比
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef unsigned long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll N = 1e6 + 5;
ll T, n, p[N], ans;
ll sum[N], f[N];
ll lmin[N], lmax[N], rmin[N], rmax[N];
ll ff(ll i) {
return i * (i + 1) * (i + i + 1) / 6;
}
bool ljudge(ll i) {
ll ld = (lmax[i] - lmin[i]) / (i - 1);
ll s = ((lmax[i] + lmin[i]) * i) >> 1; // 和
ll t = i * lmin[i] * lmin[i] + ld * lmin[i] * (i - 1) * i + ld * ld * ff(i - 1); // 平方和
return sum[i] == s && f[i] == t;
}
bool rjudge(ll i) {
ll rd = (rmax[i + 1] - rmin[i + 1]) / (n - i - 1);
ll s = ((rmax[i + 1] + rmin[i + 1]) * (n - i)) >> 1; // 和
ll t = (n - i) * rmin[i + 1] * rmin[i + 1] + rd * rmin[i + 1] * (n - i - 1) * (n - i) + rd * rd * ff(n - i - 1); // 平方和
return sum[n] - sum[i] == s && f[n] - f[i] == t;
}
int main(void) {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
cin >> T;
while (T--) {
ans = 0;
cin >> n;
for (ll i = 1; i <= n; i++) {
cin >> p[i];
sum[i] = sum[i - 1] + p[i];
f[i] = f[i - 1] + p[i] * p[i];
lmin[i] = p[i], lmax[i] = p[i];
rmin[i] = p[i], rmax[i] = p[i];
}
lmax[0] = 0, rmax[n + 1] = 0;
lmin[0] = INF, rmin[n + 1] = INF;
for (ll i = 1; i <= n; i++) {
lmin[i] = min(lmin[i - 1], p[i]);
lmax[i] = max(lmax[i - 1], p[i]);
rmin[n + 1 - i] = min(rmin[n + 2 - i], p[n + 1 - i]);
rmax[n + 1 - i] = max(rmax[n + 2 - i], p[n + 1 - i]);
}
for (ll i = 1; i < n; i++) {
bool flag = true;
if (i > 1) {
if ((lmax[i] - lmin[i]) % (i - 1) == 0) {
flag &= ljudge(i);
} else {
flag = false;
}
}
if (!flag) continue;
if (i < n - 1) {
if ((rmax[i + 1] - rmin[i + 1]) % (n - i - 1) == 0) {
flag &= rjudge(i);
} else {
flag = false;
}
}
if (!flag) continue;
ans++;
}
cout << ans << endl;
}
return 0;
}
赛时水ac了