题意简述:给定一序列,下即为序列p,问序列可否有n,m,c,s四个数按如下关系构造
①长度为n;
②p[1]=s%m;
③当i>2时,p[i]=(p[i-1]+c)%m;
④0<=c<m
当序列p无法由n,m,c,s构造时,输出-1,当可以构造但无法确定m时输出0,否则输出m和c
解析:
如果序列p可以由n,m,s,c构造,则有以下关系
①如果p[i]>p[i-1],那么c=p[i]-p[i-1];
②如果p[i]<p[i-1],那么由p[i]=(p[i-1]+c)%m&&c<m可得p[i]=p[i-1]+c-m,即有c-m=p[i]-p[i-1];
所以,我们可以得到n,m,c,s不能构造出序列p的条件:c,m-c的值不唯一
当我们确定能够构造出p时,需要考虑的问题就是能否确定m和c了,不能确定m或c的条件有:
①当序列p的所有元素都相等时,此时只能确定c=0,无法确定m的值
②对任意i(符合约束),都符合p[i]>p[i-1]或都符合p[i]<p[i-1],此时只能得到c和m-c的一个
③当n<=2时,此时至多只存在一个关系式,无法解出两个未知数
剩下的情况便是可以解除m和c的具体值了,此时需要注意序列p任意元素都对m取余,所以p的所有元素都要小于m,还有初始条件c<m
AcCode
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<cstring>
#define int long long
using namespace std;
const int N = 3e5 + 100;
int value[N];
signed main() {
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
int n, maxm = -1;
cin >> n;
set<int> fir, sec;
//fir:c;sec:c-m
int cnt = 0;//value[i]==value[i-1],即c等于0的个数
for (int i = 1; i <= n; i++) cin >> value[i];
for (int i = 2; i <= n; i++) {
if (value[i] == value[i - 1]) cnt++;
else if (value[i] > value[i - 1]) fir.insert(value[i] - value[i - 1]);
else sec.insert(value[i] - value[i - 1]);
maxm = max(maxm, value[i]);
}
if (n <= 2 || cnt == n - 1 || (!fir.size() && sec.size() == 1 && !cnt) || (fir.size() == 1 && !sec.size() && !cnt)) {
cout << 0 << endl;
//n==1||n==2,只能求出c或c-m,无法求得具体数
//为常数序列,c=0,m>value[1]
//当不为常数序列时,如果单增或单减,则只能确定c和c-m中的一个
}
else if (sec.size() > 1 || fir.size() > 1 || (cnt && cnt < n - 1)) {
cout << -1 << endl;
//部分常数序列,c,c-m不为定值,矛盾
}
else {
//当c,c-m确定后,可以求出c和m
int c = *fir.begin();
int temp = *sec.begin();
int m = c - temp;
maxm = max(maxm, value[1]);
//限制条件,最大值小于m且c<m
if (m <= c || maxm >= m) cout << -1 << endl;
else cout << m << " " << c << endl;
}
}
}