CCPC2018桂林G. Greatest Common Divisor —— 数学*

链接

题意:

给出n个数,每次操作可以使所有数加一,试寻找最小的操作次数k使得这n个数的gcd > 1,若始终无法达到则输出-1

思路:

如果最后的gcd>1,那么n个数每个数都是gcd的倍数,那么他们的差值也是gcd的倍数,所以求所有差值(排序后)的gcd,如果gcd==1,则没有办法使他们的gcd>1,但是需要特判下如果所有的数都相等而且>=2,那么0次就够了,如果==1的话则需要都加1.对于其他情况的话,暴力求出来gcd的因子,然后对于随便一个数验证次数,取一个最小值即可。 注意最后暴力的时候时间复杂度为O(sqrt(gd)),但需要特判i = gd的情况

// Decline is inevitable,
// Romance will last forever.
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
#define fi first
#define se second
#define ll long long
#define LL long long
#define int long long
#define endl '\n'
const int maxn = 1e5 + 10;
const int maxm = 1e3 + 10;
const int INF = 0x3f3f3f3f;
//const int dx[] = {0, 0, -1, 1}; //{0, 0, 1, 1, 1,-1,-1,-1}
//const int dy[] = {1, -1, 0, 0}; //{1,-1, 1, 0,-1, 1, 0,-1}
const int P = 998244353;
int n;
int t = 0;
int a[maxn];
LL gcd(LL a, LL b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}
void solve() {
    cin >> n;
    for(int i = 1; i<= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);
    if(n == 1) {
        if(a[1] == 1) cout << 1 << '\n';
        else cout << 0 << '\n';
        return;
    }
    bool ok = true;
    for(int i = 1; i < n; i++) {
        if(a[i] != a[i+1]) {
            ok =false;
            break;
        }
    }
    if(ok) {
        if(a[1] == 1) cout << 1 << '\n';
        else cout << 0 << '\n';
        return;
    }
    int gd = a[2] - a[1];
    for(int i = 3; i <= n; i++)
    gd = gcd(gd, a[i] - a[i-1]);
    if(gd == 1) {
        cout << -1 << '\n';
        return;
    }
    /*if(gcd(a[1], gd) > 1) {
        cout << 0 << '\n';
        return;
    }
     */
    int m_ans = (a[1] + gd - 1)/ gd * gd - a[1];
    for(int i = 2; i * i <= gd; i++) {
        if(gd % i == 0) {
            int tmp = (a[1]+i-1)/i * i;
            m_ans = min(m_ans, tmp - a[1]);
        }
    }
    cout << m_ans << '\n';

}
signed main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//    int T; scanf("%d", &T); while(T--)
//    freopen("1.txt","r",stdin);
//    freopen("2.txt","w",stdout);
    int T; cin >> T; while(T--) {
        cout << "Case " << ++t << ": ";
        solve();
    }
    return 0;
}
/*
 
 
 
 */

猜你喜欢

转载自blog.csdn.net/m0_59273843/article/details/121071332