Greatest Common Divisor题解(2018ccpc桂林)

https://vjudge.net/problem/Gym-102823G
在这里插入图片描述在这里插入图片描述

题意

给定一个长度为n的整型数组,每次操作给数组中每个值加上1,求最少多少次操作后可以他们的gcd不为1。

分析

一个有序数组的gcd为g,则这个有序数组中每一对相邻的数组的差的gcd必含有因子g
证明如下:

  1. 设数组{a,b,c}的gcd为g;
  2. 令a = a1g,b = a2g,c = a3g;
  3. 则b - a = (a2 - a1 )g ,c - b = (a3 - a2)g
  4. 则(b - a)于 (c - b)含有共同因子g
  5. 由此推得:一个数组{a1,a2,a3,……,an}gcd为g
  6. 则{a2 - a1,a3 - a2,……,an - an-1}的gcd含有因子g

由此可得,若进行+1操作后的数组的gcd一定是他们相邻的差的gcd的因子之一。而他们相邻的差是不会因为他们的进行多少次+1操作而改变。所以我们可以先求原数组相邻的差的gcd再将这个gcd唯一分解,找出那个符合题目条件的因子。

AC代码

#include <bits/stdc++.h>

using namespace std;

long long a[100005];

long long solve(int);

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        printf("%lld\n", solve(i));
    return 0;
}

long long solve(int qqq)
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    sort(a + 1, a + 1 + n);//排序变成有序数组
    cout << "Case " << qqq << ": ";
    long long gcd = -1;
    for (int i = 2; i <= n; i++)
    {
        long long d = a[i] - a[i - 1];
        if (!d)
            continue;
        if (gcd == -1)
            gcd = d;
        else
            gcd = __gcd(gcd, d);
    }
    if (gcd == -1 && a[1] != 1)//若全部相等并且值不为1则不需要+1
        return 0;
    if (gcd == -1 && a[1] == 1)//若全部相等并且值为1,则只要+1即可
        return 1;
    if (gcd == 1)//若gcd为1,则不论多少次+1都无法得到符合题目条件的数组
        return -1;
    long long gcds = gcd;
    vector<long long> f;
    for (long long i = 2; i * i <= gcd; i++)
    {
    	//唯一分解
        if (gcd % i == 0)
        {
            f.push_back(i);
            while (gcd % i == 0)
                gcd /= i;
        }
    }
    if (gcd > 1)
        f.push_back(gcd);
    long long ans = 1e18;
    for(auto i : f)
    {
        if(a[1] % i == 0) ans = 0;
        ans = min (ans, i - (a[1] % i));
    }
    return ans;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值