.article-info-tag,button{text-transform:uppercase}.day,.postMeta,.postSticky{position:relative}.postTitle a:link,html{-webkit-tap-highlight-color:transparent}#blog-calendar,.code-copay-btn,.code-hljs-len,.hidden{visibility:hidden}#EntryTag,#blogTitle h1{margin-top:20px}#EntryTag a,.postSticky{background:#6fa3ef}#blogTitle h1 a:hover,.dayTitle a,a,a:active,a:link,a:visited{color:#5c8ec6}#calendar table a:hover,#navList a:hover,.postDesc a:hover,a:active,a:hover,a:link,a:visited,button{text-decora…ryTag a:visited{color:#666}#BlogPostCategory a,#EntryTag a{height:20px;line-height:20px;color:#fff!important;padding:3px 5px;border-radius:3px;margin:2px 5px 0;text-decoration:none;font-size:14px}#BlogPostCategory a:hover,#EntryTag a:hover{transition:all .3s linear 0s;opacity:.8}#topics .postDesc{padding-left:0;width:100%;text-align:left;color:#666;margin-top:5px;background:0 0}.feedbackListSubtitle-louzhu:after,.feedbackListSubtitle:after,.feedbackListSubtitle:before{top:11px;right:100%;left:-1

CF1484B Restore Modulo 题解

\(\text{Description}\)

给定长度为 \(n\) 的序列 \(a\),求是否存在最大的 \(m\) 使得 \(a\) 在模意义下是等差数列。

\(\text{Solution}\)

首先我们要知道 \(a_i\) 只有可能由以下两个式子推得:

\[a_i=a_{i-1}+c\quad(1) \]

\[a_i=a_{i-1}+c-m\quad(2) \]

若由 \((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)\)

自己推下式子就可以证明了。

\(\text{Code}\)

/*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;
}
posted @ 2021-04-08 19:37  feicheng  阅读(100)  评论(0编辑  收藏  举报