4kyu Smallest possible sum

4kyu Smallest possible sum

题目背景:

Task
Given an array X of positive integers, its elements are to be transformed by running the following operation on them as many times as required:

if X[i] > X[j] then X[i] = X[i] - X[j]

When no more transformations are possible, return its sum (“smallest possible sum”).

Example
For instance, the successive transformation of the elements of input X = [6, 9, 21] is detailed below:

X_1 = [6, 9, 12] # -> X_1[2] = X[2] - X[1] = 21 - 9
X_2 = [6, 9, 6]  # -> X_2[2] = X_1[2] - X_1[0] = 12 - 6
X_3 = [6, 3, 6]  # -> X_3[1] = X_2[1] - X_2[0] = 9 - 6
X_4 = [6, 3, 3]  # -> X_4[2] = X_3[2] - X_3[1] = 6 - 3
X_5 = [3, 3, 3]  # -> X_5[1] = X_4[0] - X_4[1] = 6 - 3

题目分析:
本道题第一眼看下去就是很绕, 但是细细地思索下去会发现,既然我最终的目的是整个数组里面的每个值都是相等的,那么我可以每次只比较两个值,例如第一次比对 X[0] 和 X[1],连续套用这个算法形式,把两个值最后变成一样的,即 X’[0] = X’[1],再继续往后推进,比对 X’[1] 和 X[2],使得 X"[1] = X’[2],因为上一步中 X’[0] = X’[1],所以 X’[0] 肯定可以和 X’[1] 进行同等的变换,即满足 X"[0] = X"[1] = X’[2],大致思路就是不断地向数组尾部推进,直至推到数组尾部,题目解完,时间复杂度为 O(n)。同时需要注意到的是,题目存在一个trick,就是如果有一个元素是1的话,那么肯定数组最后会变为元素全为1的数组,考虑这一个因素进去后,可以进一步优化时间。

先附上比对两个值的算法:

unsigned long long step (unsigned long long tmp, unsigned long long start) {
    while ( tmp != start ) {
        if ( tmp > start ) {
            if ( tmp % start == 0 ) return start;
            tmp %= start;
        }
        else {
            if ( start % tmp == 0 ) return tmp;
            start %= tmp;
        }
    }
    return tmp;
}

AC代码:

#include <vector>

unsigned long long step (unsigned long long tmp, unsigned long long start) {
    while ( tmp != start ) {
        if ( tmp > start ) {
            if ( tmp % start == 0 ) return start;
            tmp %= start;
        }
        else {
            if ( start % tmp == 0 ) return tmp;
            start %= tmp;
        }
    }
    return tmp;
}

unsigned long long solution(const std::vector<unsigned long long>& arr){
    if ( arr.size() == 1) return arr[0];
    unsigned long long tmp;
    unsigned long long start = arr[0];
    for ( long long i = 1; i < arr.size(); i++ ) {
        tmp = arr[i];
        tmp = step(tmp, start);
        if ( tmp == 1 ) return arr.size();
        start = tmp;
    }
    return tmp * arr.size();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值