程序员老鬼

在大厂,一位年薪300W的P9告诉我,领导最烦这种下属,哪怕技术再牛逼,也不会给晋升机会。。

刚看到个贴子,说在大厂,一个年薪300万的P9分享:领导最烦那种只顾技术、不懂汇报、不和人打交道的下属。哪怕技术再强,也升不上去。

Image

我觉得这事挺现实的。网友们都说“技术牛逼还不够”,其实真的是。公司不是技术竞赛,是资源博弈场。你能不能让领导省心、让团队顺畅,往往比你代码写得多快更重要。别以为会点AI、搞点架构就能封神,职场升迁看的从来不是“最能干的”,而是“最有用的”。

当然,有人反感这种“拍马屁文化”,觉得不公平。但换个角度看,职场就是组织协作,领导不信任你、不懂你的价值,怎么敢把位子交给你?

说到底,技术是敲门砖,关系是门把手。【备注:文末可领最新资料】

算法题:完全子集的最大元素和

这个题叫「完全子集的最大元素和」,先把题意用大白话说一下:

有个数组 nums,下标从 1 开始,到 n 结束。你要选出一批下标,比如 {i₁, i₂, …, ik},要求这批下标里任意两两相乘,结果都是完全平方数(比如 1,4,9,16… 这种)。这样的下标集合叫「完全集」。题目让我们在所有完全集里,选一个,让对应的元素和 nums[i₁] + ... + nums[ik] 最大。

因为 nums[i] 都是正整数,所以直觉上:只要一堆下标能一起组成一个完全集,那就把这一堆里所有下标都拿上,和肯定比只拿其中一部分更大。

怎么理解「i * j 是完全平方数」?

关键条件是:对完全集里任意两个下标 i 和 j,都有 i * j 是完全平方数。

完全平方数有个经典结论: 把一个数做质因数分解,x = p1^a1 * p2^a2 * ...它是完全平方数,当且仅当每个指数 a1, a2, ... 都是偶数。

那 i * j 是完全平方数,就说明:i 和 j 分解后,把每个质因数的指数加起来,结果都是偶数。

这意味着什么? 对每个质因数 p,i 里面 p 的指数和 j 里面 p 的指数,奇偶性必须相同:

  • 要么俩都是奇数
  • 要么俩都是偶数

所以我们完全可以只关心「每个质因数指数的奇偶性(模 2)」,不用管具体是几次方。

把下标「压扁」成一个标识

更进一步,可以给每个下标 i 贴一个「标签」:

  1. 把 i 做质因数分解。
  2. 对每个质数,指数是偶数就当 0,是奇数就当 1。
  3. 把所有「指数是奇数」的质因数乘起来,得到一个数,记为 core(i)。

这个 core(i) 就是 i 去掉所有平方因子后的「平方自由部分」(有时候也叫「平方因子核」)。比如:

  • i = 12 = 2^2 * 3^1,指数奇偶:2(偶),3(奇),所以 core(12) = 3
  • i = 18 = 2^1 * 3^2,指数奇偶:2(奇),3(偶),所以 core(18) = 2
  • i = 36 = 2^2 * 3^2,全是偶数,core(36) = 1

现在看 i * j 的质因数指数,就是把它们的奇偶向量相加(模 2),要变成全 0,只有一种情况: 两人的奇偶向量一模一样。

翻译一下就是:

对于两个下标 i 和 j,i * j 是完全平方数 ⇔ core(i) == core(j)。

那题目的限制就非常清晰了:

一堆下标能组成一个完全集,当且仅当这堆下标的 core(i) 全都相同。

所以所有完全集就是:

  • 把下标 1..n 按 core(i) 分组
  • 每一组内部随便怎么选,下标们彼此都能组成完全集
  • 全是正数,那当然是「这个组全要」最好

于是问题就变成了:

按 core(i) 把下标分组,每组把对应的 nums[i] 全加起来,最后取一个最大的组和。

算法步骤梳理一下

整体思路其实很简单,就是「分组 + 求和」:

  1. 用一个线性筛预处理 1..n 每个数的最小质因数(spf),方便后面快速分解下标。

  2. 对每个下标 i(注意是下标,不是 nums[i]):

  • 用 spf 做质因数分解,统计每个质因数指数的奇偶性;
  • 把所有指数为奇数的质因数乘起来,当成这个下标的 core(i)。
  • 用一个 HashMap<Integer, Long>,键是 core(i),值是这一组的元素和。

    • 遍历下标 i,对 core(i) 对应的那一组,加上 nums[i - 1](Java 里数组是 0 下标)。
  • 再扫一遍 map,找到最大的那一组的和,就是答案。

  • 时间复杂度大概是:

    • 筛最小质因数:O(n log log n)
    • 每个下标用 spf 分解:均摊 O(log n),总共 O(n log n)在 n ≤ 1e4 的限制下完全够用。

    Java 实现代码

    直接给一个比较完整、还能直接丢到 LeetCode 上跑的写法:

    import java.util.*;

    publicclassSolution{

    publiclongmaximumSum(int[] nums){
    int n = nums.length;
    // 下标从 1..n,用到 n 即可
    int[] spf = buildSpf(n);  // smallest prime factor

            Map<Integer, Long> groupSum = new HashMap<>();

    for (int i = 1; i <= n; i++) {
    int core = getCore(i, spf);
    long old = groupSum.getOrDefault(core, 0L);
                groupSum.put(core, old + nums[i - 1]);
            }

    long ans = 0;
    for (long v : groupSum.values()) {
    if (v > ans) ans = v;
            }
    return ans;
        }

    // 线性或类线性筛最小质因数,这里简单一点写
    privateint[] buildSpf(int n) {
    int[] spf = newint[n + 1];
    for (int i = 2; i <= n; i++) {
    if (spf[i] == 0) { // i 是质数
                    spf[i] = i;
    if ((long) i * i <= n) {
    for (int j = i * i; j <= n; j += i) {
    if (spf[j] == 0) {
                                spf[j] = i;
                            }
                        }
                    }
                }
            }
    // 可能有少量合数没被标到(比如 2 * 质数 > n 时),补一下
    for (int i = 2; i <= n; i++) {
    if (spf[i] == 0) spf[i] = i;
            }
    return spf;
        }

    // 计算下标 i 的 square-free 核心 core(i)
    privateintgetCore(int x, int[] spf){
    int core = 1;
    while (x > 1) {
    int p = spf[x];
    int cnt = 0;
    while (x % p == 0) {
                    x /= p;
                    cnt ^= 1; // 只关心奇偶
                }
    if (cnt == 1) {
                    core *= p;
                }
            }
    return core;
        }

    // 简单测一下
    publicstaticvoidmain(String[] args){
            Solution s = new Solution();
    int[] nums1 = {8,7,3,5,7,2,4,9};
            System.out.println(s.maximumSum(nums1)); // 16

    int[] nums2 = {5,10,3,10,1,13,7,9,4};
            System.out.println(s.maximumSum(nums2)); // 19
        }
    }

    整套下来,其实就是一句话:

    把「两两下标乘积是完全平方数」翻译成「下标按平方自由核分组」,然后在每组里把 nums 求和取最大。

    数学味儿稍微有一点,但搞清楚「只看质因数指数奇偶性」这件事之后,代码其实挺顺的。

    -END-

    我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

    最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领,也可以链接我微信:hls404