标签:意义 mat 排除 sts play putc text pre ref
给定长度为 \(n\) 的序列 \(a\),求是否存在最大的 \(m\) 使得 \(a\) 在模意义下是等差数列。
首先我们要知道 \(a_i\) 只有可能由以下两个式子推得:
若由 \((1)\) 转移来,则说明 \(a_i \ge a_{i-1}\) ,反之则有 \(a_i < a_{i-1}\)。
结论:构造差分序列 \(b\),\(b_i=a_i-a_{i-1}\) 若有解,则 \(b\) 中最多只有两个不相同的数字
证明:
考虑分类讨论,若由上述 \((1)\) 转移来。则 \(b_i = c\),反之 \(b_i=c-m\)。
特殊地:如果 \(b\) 是常数列,则 \(m\) 可取任何值。
如果 \(\forall i\in[1,n],\exists b_i < 0\) 则无解。
排除上述情况之后就可以来计算 \(m,c\) 的值了:
记 \(b\) 中不同的两项数字为 \(p,q\) ,则:
\(m = |p|+|q|,c=\max(p,q)\)
自己推下式子就可以证明了。
/*If you are full of hope,you will be invincible*/
constexpr int N = 1e5 + 10;
int a[N],b[N],n,T;
std::unordered_map <int,bool> vis;
int num,ans,ans_;
inline void Solve() {
vis.clear(),num=ans=ans_=0;
int mx = -1,tmp[3];
read(n);
memset(a,0,sizeof a),memset(b,0,sizeof b);
for(int i = 1;i <= n;++i) read(a[i]),mx=max(a[i],mx);
if(n == 1) return ans = 0,void();
for(int i = 2;i <= n;++i) b[i-1] = a[i] - a[i-1];//差分
int num = 0;
for(int i = 1;i <= n-1;++i) {
if(!vis[b[i]]) tmp[++num] = b[i],vis[b[i]] = 1;
if(num == 3) return ans = -1,void();//如果有三个不同的数
}
if(num == 1) return ans = 0,void();
if(tmp[1] < 0 and tmp[2] < 0) return ans = -1,void();
ans = abs(tmp[1]) + abs(tmp[2]),ans_ = max(tmp[1],tmp[2]);
if(ans < mx) return ans = -1,void();
}
int main(int argc,const char **argv) {
read(T);
while(T--) {
Solve();
if(ans == -1 || ans == 0) print(‘\n‘,ans);
else print(‘ ‘,ans,ans_),STD::putc(‘\n‘);
}
return STD::flush(),0;
}
标签:意义 mat 排除 sts play putc text pre ref
原文地址:https://www.cnblogs.com/hl-fc/p/14634406.html