[CF-GYM]Abu Tahun Mod problem题解

前言
这道题比较简单,但我还是想了好一会
题意简述
Abu Tahun很喜欢回文。
一个数组若是回文的,那么它从前往后读和从后往前读都是一样的,比如数组\(\left\{1\right\},\left\{1,1,1\right\},\left\{1,2,1\right\},\left\{1,3,2,3,1\right\}\)都是回文数组,但是数组\(\left\{11,3,5,11\right\},\left\{1,12\right\}\)不是回文的。
Abu Tahun有个包含\(n\)个整数的数组\(A\),他想让它变成回文的。他可以任意选择一个整数\(m\),然后让所有元素\(A_i\) 变成\(A_i\ mod\ m\)
求最大的\(m\)的值。
输入格式
第一行一个整数\(n\)\(\left(1 \leq n \leq 10^5\right)\)
第二行\(n\)个整数\(A_1,A_2,\dots,A_n\)\(\left(1 \leq A_i \leq 10^9\right)\)
输出格式
输出最大的Abu Tahun能取的\(m\)的值,如果\(m\)可以是任意大小输出\(-1\)
样例
---------------------------------------------------
 Input                     output
---------------------------------------------------
  4                              -1
  1 1 1 1
---------------------------------------------------
  4                               1
  1 2 3 4
---------------------------------------------------
  3                               8
  8 12 16
---------------------------------------------------
数据范围与约定
\(50\%\)的数据\(1 \leq n, A_i \leq 1000\)
\(100\%\)的数据\(1 \leq n \leq 10^5, 1 \leq A_i \leq 10^9\)
解法
我们发现对于每一组\([A_i,A_{n - i + 1}]\),有两种方法使其变为0,第一种是mod两个数的差的任意一个约数,第二种是mod两个数的gcd使之都变为0,根据辗转相减,我们发现第一种完全包含第二种,因此只需考虑第一种情况。
那么对于\(A\)数组,只需要枚举所有的\([A_i,A_{n - i + 1}]\),然后用它们的差求一个gcd即可
代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;

inline ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

ll gcd(ll a, ll b){
    if (b > a) swap(a, b);
    while (b > 0){
        ll tmp = a % b;
        a = b, b = tmp;
    }
    return a;
}

ll a[100005];

int main(){
    freopen("palindrome.in", "r", stdin);
    freopen("palindrome.out", "w", stdout);
    int n = read(); int flg = (n <= 1000) ? 1 : 0, is_same = 1;
    for (int i = 1; i <= n; ++i)
        a[i] = read(), flg = (a[i] <= 1000) ? (flg & 1) : 0;
    for (int i = 1; i <= n; ++i)
        is_same = (a[i] == a[n - i + 1]) ? (is_same & 1) : 0;
    if (is_same){
        printf("-1");
        return 0;
    }
    /*//brute force
    if (flg){
        int m = (n >> 1);
        for (int i = 1000; i >= 1; --i){
            int j;
            for (j = 1; j <= m; ++j)
                if ((abs(a[j] - a[i])) % i != 0 && gcd(a[i], a[j]) % i != 0)
                    break;
            if (j == m + 1){
                printf("%d", i);
                return 0;
            }
        }
    }*/
    ll _gcd = 0; int m = n >> 1;
    for (int i = 1; i <= m; ++i){
        ll y = abs(a[i] - a[n - i + 1]);
        _gcd = gcd(_gcd, y);
    }
    if (gcd == 0)
        printf("-1");
    else
        printf("%lld", _gcd);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/linzhengmin/p/10890345.html
mod
今日推荐