题意是给一个长度为n的数组,判断是否存在m,s,c使得满足如下的条件
- a 1 = s m o d m a_{1} = s \ mod \ m a1=s mod m
- a i = ( a i − 1 + c ) m o d m f o r a l l i ∈ 1 < i ≤ n a_{i} = (a_{i - 1} + c) \ mod \ m \ for \ all \ i \in 1 < i \le n ai=(ai−1+c) mod m for all i∈1<i≤n
如果不存在,输出-1, 如果存在,输出最大的m以及任意合适的c(0 <= c < m),如果m可以无限大,输出0
如果,n = 5,a = [3, 0, 4, 1, 5] ,那么m = 7, c = 4, s = 10
前提:所有的a[i] < m, c < m
,故(a[i] + c ) / m = 1
假设c = 0
,那么a[i] = a[i - 1] % m
,故所有的a[i] = a[i - 1]
,这时候m可以取无限大,如果只有部分的a[i] = a[i - 1]
,那么这时候的m不存在,因为当a[i[ != a[i - 1]
,c不能等于0,与之前的假设矛盾
当c != 0
时,如果存在a[i] = a[i - 1]
的情况,这时候m也不存在,原因同上
如果a [i] + c >= m
,则(a[i] + c) % m
等价于 a[i] + c - m = a[i] - (m - c)
,相当于减去一个负数
如果a[i] + c < m
,则(a[i] + c) % m
等价于 a[i] + c
,相当于加上一个正数
要保证m存在则需要保证任意一个a[i] - a[i - 1]
的结果出现的正数/负数都相等
如果它们的差都是同一个正数或者负数,则m可以取无限大
如果结果中出现多个正数或者多个负数,m不存在
只有一个正数和一个负数的情况下,正数为c,那么负数为c - m,则m = c - (c - m)
接下来只要检查是否所有的相邻的数都满足以上的规则
在这里插入代码片
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <unordered_set>
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N];
void solve() {
cin >> n;
int same = 0;
cin >> a[1];
// 如果n == 1,则m可以无限大
if(n == 1) {
cout << 0 << endl;
return ;
}
unordered_set<int> st;
for(int i = 2; i <= n; i++) {
cin >> a[i];
if(a[i] == a[i - 1]) same++;
st.insert(a[i] - a[i - 1]);
}
// 如果存在相同的个数
if(same) {
if(same == n - 1) {
cout << 0 << endl;
} else {
cout << -1 << endl;
}
} else {
// 只有一个正数或者只有一个负数的情况
if(st.size() == 1) cout << 0 << endl;
// 如果不同的差的数量大于2,则m不存在
else if(st.size() > 2) cout << -1 << endl;
else {
// 计算出m和c 判断是否满足条件
int k1 = *st.begin(), k2 = *(++st.begin());
if(k1 > 0 && k2 > 0 || k1 < 0 && k2 < 0) cout << -1 << endl;
else {
int m = abs(k1) + abs(k2), c = k1 > 0 ? k1 : k2;
// a[1] 也需要满足小于 m
bool flag = a[1] < m;
for(int i = 2; i <= n && flag; i++) {
if((a[i - 1] + c) % m != a[i]) {
flag = false;
break;
}
}
if(flag) cout << m << ' ' << c << endl;
else cout << -1 << endl;
}
}
}
}
int main() {
// freopen("in.txt", "r", stdin);
int t;
cin >> t;
while(t--) solve();
return 0;
}