Restore Modulo

CF题目链接

题意简述:给定一序列,下即为序列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;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值