Codeforces 1484 B. Restore Modulo(思维+细节处理)

传送门


题目大意

给出初始的三个数 s , m , c ( 0 ≤ c < m ) s,m,c(0 \leq c < m) s,m,c(0c<m),可以通过如下递推得出的一个序列 a a a

  • a 1 = s % m a_1 = s\%m a1=s%m
  • a i = ( a i − 1 + c ) % m , i ≥ 2 a_{i} = (a_{i-1} + c)\%m,i \geq 2 ai=(ai1+c)%m,i2

现在反过来,给出一个含有 n n n个数的序列 a a a,问能否求出 m , c m,c m,c,若 m m m可以为无穷大则输出 0 0 0,若不存在 m m m则输出 − 1 -1 1

解题思路

这题作为 B B B题也有点太难了,无语。

首先本题最重要的一个条件是 0 ≤ c < m 0 \leq c <m 0c<m,抓紧这个条件研究序列能发现:

  • a i + 1 > a i a_{i+1}>a_i ai+1>ai,那么 a i + 1 − a i = c a_{i+1} - a_i = c ai+1ai=c
  • 因为 a i < m ( ∀ i ∈ [ 1 , n ] ) a_i <m ( \forall i \in [1,n]) ai<m(i[1,n]),因此 a i + c < 2 ∗ m a_i+c<2*m ai+c<2m,那么只要 a i + 1 < a i a_{i+1}<a_i ai+1<ai,我们就能求出 m = a i + c − a i + 1 m = a_i + c - a_{i+1} m=ai+cai+1,且这个 m m m一定是唯一的。
  • 固定 s , m s,m s,m然后 c c c m − 1 m-1 m1开始递减,手玩可以发现如果整个序列是递减的合法序列那么一定是等差递减,这时 m = i n f m = inf m=inf,否则就不存在这样递减的序列。同理等差递增的序列。
  • 若存在 a i = a i + 1 a_i =a_{i+1} ai=ai+1,那么 c = 0 c=0 c=0,序列合法当且仅当序列的所有数都相等。

还有一个特判, n = 1    ∣ ∣    n = 2 n = 1 ~~||~~ n=2 n=1    n=2 m = i n f m = inf m=inf。另外在确定 m , c m,c m,c回代判断序列是否合法时注意还要判断 a i < m a_i < m ai<m,我就倒在了这个点结果写不出来。

//
// Created by Happig on 2021/3/21.
//
#include <bits/stdc++.h>
#include <unordered_map>

using namespace std;
#define ENDL "\n"
#define lowbit(x) (x & (-x))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 10;

int a[maxn];
int n;

bool check(int m, int c) {
    
     //确定m,c检查是否合法
    if (c >= m || m <= a[1]) return 0;
    for (int i = 1; i < n; i++) {
    
    
        if (a[i] >= m || a[i + 1] >= m) return 0;
        if (a[i + 1] > a[i] && a[i + 1] - a[i] != c) return 0;
        if (a[i + 1] < a[i] && (a[i] + c) % m != a[i + 1]) return 0;
    }
    return 1;
}

bool SPJ() {
    
    
    for (int i = 1; i < n; i++) {
    
    
        if (a[i + 1] == a[i]) return 1;
    }
    return 0;
}


//0--inf  -1---不存在
int main() {
    
    
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while (T--) {
    
    
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        if (n == 1 || n == 2) {
    
    
            cout << 0 << ENDL;
            continue;
        }

        if (SPJ()) {
    
      //若有两数相等那么所有的数只有相等才合法,m = inf
            bool ok = 1;
            for (int i = 1; i <= n; i++) {
    
    
                if (a[i] != a[1]) {
    
    
                    ok = 0;
                    break;
                }
            }
            if (ok) cout << 0 << ENDL;
            else cout << -1 << ENDL;
            continue;
        }

        if (a[1] < a[2]) {
    
    
            int i = 2, c = a[2] - a[1], m;
            while (i <= n && a[i] > a[i - 1]) i++;
            if (i == n + 1) {
    
      //递增的序列
                bool ok = 1;
                int del = a[2] - a[1];
                for (int j = 1; j < n; j++) {
    
    
                    if (a[j + 1] - a[j] != del) {
    
    
                        ok = 0;
                        break;
                    }
                }
                if (ok) cout << 0 << ENDL;
                else cout << -1 << ENDL;
            } else {
    
      //能确定m,c的序列
                m = a[i - 1] + c - a[i];
                if (check(m, c)) cout << m << " " << c << ENDL;
                else cout << -1 << ENDL;
            }
        } else if (a[1] > a[2]) {
    
    
            int i = 2, m, c;
            while (i <= n && a[i] < a[i - 1]) i++;
            if (i == n + 1) {
    
      //递减的序列
                bool ok = 1;
                int del = a[1] - a[2];
                for (int j = 1; j < n; j++) {
    
    
                    if (a[j] - a[j + 1] != del) {
    
    
                        ok = 0;
                        break;
                    }
                }
                if (ok) cout << 0 << ENDL;
                else cout << -1 << ENDL;
            } else {
    
    
                c = a[i] - a[i - 1];
                m = a[i - 2] + c - a[i - 1];
                if (check(m, c)) cout << m << " " << c << ENDL;
                else cout << -1 << ENDL;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/115102472