Leetcode.2862 完全子集的最大元素和

题目链接

Leetcode.2862 完全子集的最大元素和 rating : 2292

题目描述

给你一个下标从 1 1 1 开始、由 n n n 个整数组成的数组。你需要从 n u m s nums nums 选择一个 完全集,其中每对元素下标的乘积都是一个 完全平方数,例如选择 a i a_i ai a j a_j aj i ∗ j i * j ij 一定是完全平方数。

返回 完全子集 所能取到的 最大元素和

示例1:
输入:nums = [8,7,3,5,7,2,4,9]
输出:16
解释:
我们选择下标为 2 和 8 的元素,并且 1 * 4 是一个完全平方数。
示例2:
输入:nums = [8,10,3,8,1,13,7,9,4]
输出:20
解释:
我们选择下标为 1, 4, 9 的元素。1 * 4, 1 * 9, 4 * 9 是完全平方数。
提示:
  • 1 ≤ n = n u m s . l e n g t h ≤ 1 0 4 1 \leq n = nums.length \leq 10^4 1n=nums.length104
  • 1 ≤ n u m s [ i ] ≤ 1 0 9 1 \leq nums[i] \leq 10^9 1nums[i]109

解法:质因数分解 + 数学

如果 i ∗ j i * j ij 是一个 完全平方数,那么 i f i × j f j \frac{i}{f_i} \times \frac{j}{f_j} fii×fjj 也是一个完全平方数。( f i , f j f_i,f_j fi,fj 分别是 i , j i,j i,j最大平方因子,即 f i , f j f_i,f_j fi,fj 也是完全平方数)。

证明过程:
如果一个数是完全平方数,那么它的每一个质因子都应该是偶数个。

因为 i ∗ j i * j ij 是完全平方数。 i ∗ j = f i ∗ i f i ∗ f j ∗ j f j i * j =f_i * \frac{i}{f_i} *f_j* \frac{j}{f_j} ij=fifiifjfjj

因为 f i , f j f_i,f_j fi,fj 也是完全平方数,所以 i f i × j f j \frac{i}{f_i} \times \frac{j}{f_j} fii×fjj 剩余的因子都应该是 偶数个,即 i f i × j f j \frac{i}{f_i} \times \frac{j}{f_j} fii×fjj 也是一个完全平方数。

举例: 2 × 18 2 \times 18 2×18 是一个完全平方数, 2 2 2 的最大平方因子为 1 1 1 18 18 18 的最大平方因子是 9 9 9 2 1 × 18 9 = 2 × 2 = 4 \frac{2}{1} \times \frac{18}{9} = 2 \times 2 = 4 12×918=2×2=4 依旧是一个完全平方数。

两个数 i , j i,j i,j,如果 i f i = j f j \frac{i}{f_i} = \frac{j}{f_j} fii=fjj,那么 i ∗ j i *j ij 就是一个完全平方数。

所以在进行 质因数分解,获取最大平方因子 f i f_i fi时,我们以 i f i \frac{i}{f_i} fii 分组,同一组内元素两两相乘都是完全平方数。直接遍历获取最大的和返回即可。

时间复杂度: O ( n × l o g n ) O(n\times logn) O(n×logn)

C++代码:

using LL = long long;

class Solution {
public:
    long long maximumSum(vector<int>& nums) {
        int n = nums.size();
        unordered_map<int,LL> cnt;

        for(int i = 1;i <= n;i++)
        {
            auto x = i;
            int f = 1;

            for(int d = 2;d <= x / d;d++)
            {
                if(x % d == 0)
                {
                    int k = 0, s = 1;
                while(x % d == 0)
                {
                    x /= d;
                    s *= d;
                    k++;
                }
                //如果k是奇数 需要去掉一个
                //比如 s = 2 * 2 * 2, 由于我们是要求最大平方因子, 所以只需要偶数个, 即 2 * 2 
                if(k & 1) s /= d;
                f *= s;
                }
            }
            //按 i / fi 分组记录记录元素和
            cnt[i / f] += nums[i - 1];
        }

        LL ans = 0;
        for(auto [k, v]:cnt)
        {
            ans = max(ans, v);
        }

        return ans;
    }
};

相关推荐

  1. Leetcode.2862 完全子集元素

    2024-06-14 09:26:04       8 阅读
  2. LeetCode 2656.K个元素

    2024-06-14 09:26:04       33 阅读
  3. LeetCode[题解] 2864. 二进制奇数

    2024-06-14 09:26:04       21 阅读
  4. leetcode 2864.二进制奇数

    2024-06-14 09:26:04       23 阅读
  5. LeetCode 2864.二进制奇数

    2024-06-14 09:26:04       22 阅读
  6. LeetCode每日一题】2864. 二进制奇数

    2024-06-14 09:26:04       22 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-14 09:26:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-14 09:26:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-14 09:26:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-14 09:26:04       20 阅读

热门阅读

  1. flume配置----a1.sources.r1.positionFile=xxxx.json

    2024-06-14 09:26:04       8 阅读
  2. 【安全函数】常用的安全函数的使用

    2024-06-14 09:26:04       6 阅读
  3. 快速入门Flutter:从零开始构建你的第一个应用

    2024-06-14 09:26:04       7 阅读
  4. C++Primer Plus编程题(第五章)

    2024-06-14 09:26:04       8 阅读
  5. Webrtc支持FFMPEG硬解码之解码实现(三)

    2024-06-14 09:26:04       11 阅读
  6. ### RabbitMQ五种工作模式:

    2024-06-14 09:26:04       10 阅读