题目大意
给出初始的三个数 s , m , c ( 0 ≤ c < m ) s,m,c(0 \leq c < m) s,m,c(0≤c<m),可以通过如下递推得出的一个序列 a a a:
- a 1 = s % m a_1 = s\%m a1=s%m
- a i = ( a i − 1 + c ) % m , i ≥ 2 a_{i} = (a_{i-1} + c)\%m,i \geq 2 ai=(ai−1+c)%m,i≥2
现在反过来,给出一个含有 n n n个数的序列 a a a,问能否求出 m , c m,c m,c,若 m m m可以为无穷大则输出 0 0 0,若不存在 m m m则输出 − 1 -1 −1。
解题思路
这题作为 B B B题也有点太难了,无语。
首先本题最重要的一个条件是 0 ≤ c < m 0 \leq c <m 0≤c<m,抓紧这个条件研究序列能发现:
- 若 a i + 1 > a i a_{i+1}>a_i ai+1>ai,那么 a i + 1 − a i = c a_{i+1} - a_i = c ai+1−ai=c。
- 因为 a i < m ( ∀ i ∈ [ 1 , n ] ) a_i <m ( \forall i \in [1,n]) ai<m(∀i∈[1,n]),因此 a i + c < 2 ∗ m a_i+c<2*m ai+c<2∗m,那么只要 a i + 1 < a i a_{i+1}<a_i ai+1<ai,我们就能求出 m = a i + c − a i + 1 m = a_i + c - a_{i+1} m=ai+c−ai+1,且这个 m m m一定是唯一的。
- 固定 s , m s,m s,m然后 c c c从 m − 1 m-1 m−1开始递减,手玩可以发现如果整个序列是递减的合法序列那么一定是等差递减,这时 m = i n f m = inf m=inf,否则就不存在这样递减的序列。同理等差递增的序列。
- 若存在 a i = a i + 1 a_i =a_{i+1} ai=ai+1,那么 c = 0 c=0 c=0,序列合法当且仅当序列的所有数都相等。
还有一个特判, n = 1 ∣ ∣ n = 2 n = 1 ~~||~~ n=2 n=1 ∣∣ n=2时 m = i n f m = inf m=inf。另外在确定 m , c m,c m,c回代判断序列是否合法时注意还要判断 a i < m a_i < m ai<m,我就倒在了这个点结果写不出来。
//
// Created by Happig on 2021/3/21.
//
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define ENDL "\n"
#define lowbit(x) (x & (-x))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 10;
int a[maxn];
int n;
bool check(int m, int c) {
//确定m,c检查是否合法
if (c >= m || m <= a[1]) return 0;
for (int i = 1; i < n; i++) {
if (a[i] >= m || a[i + 1] >= m) return 0;
if (a[i + 1] > a[i] && a[i + 1] - a[i] != c) return 0;
if (a[i + 1] < a[i] && (a[i] + c) % m != a[i + 1]) return 0;
}
return 1;
}
bool SPJ() {
for (int i = 1; i < n; i++) {
if (a[i + 1] == a[i]) return 1;
}
return 0;
}
//0--inf -1---不存在
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
if (n == 1 || n == 2) {
cout << 0 << ENDL;
continue;
}
if (SPJ()) {
//若有两数相等那么所有的数只有相等才合法,m = inf
bool ok = 1;
for (int i = 1; i <= n; i++) {
if (a[i] != a[1]) {
ok = 0;
break;
}
}
if (ok) cout << 0 << ENDL;
else cout << -1 << ENDL;
continue;
}
if (a[1] < a[2]) {
int i = 2, c = a[2] - a[1], m;
while (i <= n && a[i] > a[i - 1]) i++;
if (i == n + 1) {
//递增的序列
bool ok = 1;
int del = a[2] - a[1];
for (int j = 1; j < n; j++) {
if (a[j + 1] - a[j] != del) {
ok = 0;
break;
}
}
if (ok) cout << 0 << ENDL;
else cout << -1 << ENDL;
} else {
//能确定m,c的序列
m = a[i - 1] + c - a[i];
if (check(m, c)) cout << m << " " << c << ENDL;
else cout << -1 << ENDL;
}
} else if (a[1] > a[2]) {
int i = 2, m, c;
while (i <= n && a[i] < a[i - 1]) i++;
if (i == n + 1) {
//递减的序列
bool ok = 1;
int del = a[1] - a[2];
for (int j = 1; j < n; j++) {
if (a[j] - a[j + 1] != del) {
ok = 0;
break;
}
}
if (ok) cout << 0 << ENDL;
else cout << -1 << ENDL;
} else {
c = a[i] - a[i - 1];
m = a[i - 2] + c - a[i - 1];
if (check(m, c)) cout << m << " " << c << ENDL;
else cout << -1 << ENDL;
}
}
}
return 0;
}