首页 > 试题广场 >

k倍多重正整数集合

[编程题]k倍多重正整数集合
  • 热度指数:1448 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 128M,其他语言256M
  • 算法知识视频讲解

k倍多重正整数集合的定义是:在一个多重集合(元素可以重复)中,不存在一个正整数是另一个正整数的k倍。

现在小Mn个正整数,你可以选择其中一些数构成k倍多重正整数集合。请求出最多能选出多少数来构成它。


输入描述:
第一行有两个整数n, k(1 <= n <= 10^5, 1 <= k <= 10^9)。

接下来一行有n个正整数a1, a2, ..., an (1 <= ai <= 10^9)。


输出描述:
最多能选出多少数构成k倍多重正整数集合。
示例1

输入

6 2
2 3 6 5 4 10

输出

3

说明

第一个样例中,我们选择2,3,5即可满足要求,因为k == 2,不存在一个数是另一个数的两倍。
示例2

输入

2 2
2 2

输出

2

说明

第二个样例中,我们选择2,2即可满足要求,因为k == 2,2也不是2的两倍,注意多重集合元素可以重复。
对于成K倍数数字,排序后,相邻不能连续选 → 打家劫舍DP
import java.util.*;

// k=1:不同数字个数
// k>1:有K倍数关系的数, 一起排序, 不能连续取 → 打家劫舍DP 🔥

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n  = in.nextInt(), k = in.nextInt();
        TreeMap<Long, Integer> map = new TreeMap<>();
        for (int i = 0; i < n; i++) {
            map.merge(in.nextLong(), 1, Integer::sum);
        }

        if (k == 1) {
            System.out.println(map.size());
            return;
        }

        int res = 0;
        for (long x : map.keySet()) {
            int cur = 0, pre1 = 0, pre2 = 0;
            // x  kx  kkx ...
            while (map.containsKey(x) && map.get(x) > 0 && x <= map.lastKey()) {
                int cnt = map.get(x);
                map.put(x, 0);
                cur = Math.max(cnt + pre2, pre1); // 选&nbs***bsp;不选
                pre2 = pre1;
                pre1 = cur;
                x *= k;
            }
            res += cur;
        }
        System.out.println(res);
    }
}


发表于 2025-10-23 18:29:31 回复(0)