使最大公约数为 K 的递增/递减操作

Posted

技术标签:

【中文标题】使最大公约数为 K 的递增/递减操作【英文标题】:Increment/Decrement operation to make Greatest common divisor as K 【发布时间】:2017-12-09 14:04:35 【问题描述】:

给定一个大小为 N 的数组。

此外,我们还提供了可以将数组的任何元素递增/递减 1 的操作。

我们的目标是使所有元素的 GCD(最大公约数)在最少的操作数中等于给定数 K。

因此,我们需要找到所需的最少操作数。

示例:假设 N=3 且数组为 [4,5,6] 且 K=5 则此处的答案为 2。 我们可以通过在一次操作中减小 6 的值并在第二次操作中将值增加 4 到 5 来将 GCD 设为 5。

我的做法: 我们的最终目标是这样的:

[x1 * k,x2 * k,....x3 ∗ k],其中 gcd(x1,x2....xn)=1 (xi ∗ k 是我们替换数组元素的位置位置与)

在单独的数组 DP[i][j] 中维护状态,其中 DP[i][j] = 使 [x1,x2...xi] 的 gcd 等于 j 所需的最少操作。

答案将是 DP[N][1],其中 N 是数组的大小。

但是由于这种方法显然取决于元素的范围,并且所有元素的范围都可以达到 1000000。此外,N、K 也可以达到 1000000。

有什么更好的方法来解决这个问题。 ?

【问题讨论】:

欢迎来到 Stack Overflow。家庭作业类型的问题是可以的,但请尝试问一些比“解决这个问题有什么更好的方法?”更具体的问题 输入或输出是否允许负值? @Airhead 当然。我第一次 :) 感谢您的建议 @STF 仅限非负正整数 有专门的网页供新手使用。在这里阅读:***.com/help/asking 【参考方案1】:

这个问题是在hackerearth的一些公司招聘挑战中被问到的。我能够通过示例测试用例和我自己的一些测试用例,但不能通过任何在线法官测试用例。这是我的方法:

    def gcd(a,b):
    if b>a:
        a,b = b,a
    while b:
        a,b = b,a%b
    return a 
t = int(input())
for i in range(t):
    k,n = map(int,input().split())
    arr = [int(x) for x in input().split()]
    ops = 0
    n1 = arr[0]
    n2 = arr[1]
    g = gcd(n1,n2)
    if g!=k:
        i,j = n1%k,n2%k
        if i and j:
            ops = min(i,k-i)+min(j,k-j)
        else:
            if i:
                ops = min(k-i,i)
            elif j:
                 ops = min(k-j,j)
    for i in range(2,n):
        g = gcd(k,arr[i])
        if g!=k:
            j = arr[i]%k
            ops += min(k-j,j)
    print(ops)

其次,我的想法是遍历数组并找出转换 arr[i]%k==0 需要多少步骤并找到其中的最小值并添加到答案中,这基本上也是我的第一个方法。

t = int(input())
for i in range(t):
    k,n = map(int,input().split())
    arr = [int(x) for x in input().split()]
    ops = 0

    for num in arr:
        rem = num%k
        if rem>0:
            ops+=min(rem,k-rem)
    print(ops)

【讨论】:

【参考方案2】:

以下是我的代码在 java 中为我通过了所有测试用例

Scanner s = new Scanner(System.in);
    int t = s.nextInt();
    while (t > 0) 
        int k = s.nextInt();
        int n = s.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) 
            nums[i] = s.nextInt();
        
        long opt = 0;
        for (int num : nums) 
            if (num == k) 
                continue;
            
            if (num < k) 
                opt += k - num;
             else 
                int rem = num % k;
                if (rem > 0) 
                    opt += Math.min(rem, k - rem);
                
            
        
        System.out.println(String.valueOf(opt));
        t--;
    

【讨论】:

以上是关于使最大公约数为 K 的递增/递减操作的主要内容,如果未能解决你的问题,请参考以下文章

定时器最大接口时钟我定时时钟区别

循环数组最大子段和(动态规划思想的巧妙转换)

在递减然后递增并且可能包含重复项的列表中查找最小值

求最大递增数

codeforce-1201-C题解

LeetCode- 柱状图中最大的矩形(单调栈)