Leetcode.2338 统计理想数组的数目

给定整数n和maxValue,找到长度为n的不同理想数组的数目。理想数组要求每个元素在1到maxValue范围内,并且每个元素都能被其前一个元素整除。解决方案涉及到质因数分解和组合数学,计算每个数的质因子分配到n个位置的方案数,然后累加所有可能的起始数字的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

Leetcode.2338 统计理想数组的数目 Rating : 2615

题目描述

给你两个整数 n n n m a x V a l u e maxValue maxValue ,用于描述一个 理想数组

对于下标从 0 开始、长度为 n n n 的整数数组 a r r arr arr ,如果满足以下条件,则认为该数组是一个 理想数组

  • 每个 a r r [ i ] arr[i] arr[i] 都是从 1 m a x V a l u e maxValue maxValue 范围内的一个值,其中 0 < = i < n 0 <= i < n 0<=i<n
  • 每个 a r r [ i ] arr[i] arr[i] 都可以被 a r r [ i − 1 ] arr[i - 1] arr[i1] 整除,其中 0 < i < n 0 < i < n 0<i<n

返回长度为 n不同 理想数组的数目。由于答案可能很大,返回对 1 0 9 + 7 10^9 + 7 109+7 取余的结果。

示例 1:

输入:n = 2, maxValue = 5
输出:10
解释:存在以下理想数组:

  • 以 1 开头的数组(5 个):[1,1]、[1,2]、[1,3]、[1,4]、[1,5]
  • 以 2 开头的数组(2 个):[2,2]、[2,4]
  • 以 3 开头的数组(1 个):[3,3]
  • 以 4 开头的数组(1 个):[4,4]
  • 以 5 开头的数组(1 个):[5,5] 共计 5 + 2 + 1 + 1 + 1 = 10 个不同理想数组。
示例 2:

输入:n = 5, maxValue = 3
输出:11
解释:存在以下理想数组:

  • 以 1 开头的数组(9 个):
    • 不含其他不同值(1 个):[1,1,1,1,1]
    • 含一个不同值 2(4 个):[1,1,1,1,2], [1,1,1,2,2], [1,1,2,2,2], [1,2,2,2,2]
    • 含一个不同值 3(4 个):[1,1,1,1,3], [1,1,1,3,3], [1,1,3,3,3], [1,3,3,3,3]
  • 以 2 开头的数组(1 个):[2,2,2,2,2]
  • 以 3 开头的数组(1 个):[3,3,3,3,3] 共计 9 + 1 + 1 = 11 个不同理想数组。
提示:
  • 2 < = n < = 1 0 4 2 <= n <= 10^4 2<=n<=104
  • 1 < = m a x V a l u e < = 1 0 4 1 <= maxValue <= 10^4 1<=maxValue<=104

解法:质因数分解 & 组合数学

由于 理想数组 a r r [ i − 1 ] arr[i-1] arr[i1] 能整除 a r r [ i ] arr[i] arr[i],如果 a r r [ i ] = 2 × a r r [ i − 1 ] arr[i] = 2 \times arr[i-1] arr[i]=2×arr[i1] ,即每次扩大一倍的话。

由于 a r r [ i ] ≤ 1 0 4 arr[i] \leq 10^4 arr[i]104所以 理想数组 的最大扩大次数为 ⌈ l o g 2 10000 ⌉ = 13 \lceil log_2^{10000} \rceil = 13 log210000=13

我们可以考虑 理想数组 的第一项都是从 1 1 1 开始的。

假设 n = 5 n = 5 n=5 且 最后一个元素是 8 8 8,所谓的 理想数组 实际上就是把 8 8 8 的质因子,分摊到 这 5 5 5 个位置上: [ 1 , 1 , 1 , 1 , 1 ] [1,1,1,1,1] [1,1,1,1,1]

  • [ × 2 , _ , _ , × 2 , × 2 ] [\times 2,\_,\_,\times 2,\times 2] [×2,_,_,×2,×2],等价于 [ 2 , 2 , 2 , 4 , 8 ] [2,2,2,4,8] [2,2,2,4,8]
  • [ × 2 , × 2 , _ , _ , × 2 ] [\times 2,\times 2,\_,\_,\times 2] [×2,×2,_,_,×2],等价于 [ 2 , 4 , 4 , 4 , 8 ] [2,4,4,4,8] [2,4,4,4,8]
  • [ × 4 , × 2 , _ , _ , _ ] [\times 4,\times 2,\_,\_,\_] [×4,×2,_,_,_],等价于 [ 4 , 8 , 8 , 8 , 8 ] [4,8,8,8,8] [4,8,8,8,8]
  • [ × 8 , _ , _ , _ , _ ] [\times 8,\_,\_,\_,\_] [×8,_,_,_,_],等价于 [ 8 , 8 , 8 , 8 , 8 ] [8,8,8,8,8] [8,8,8,8,8]

我们要做的就是求出所有的这些方案。

因为 理想数组 的最后一项元素 x x x 可以被分解为:

x = p 1 c 1 × p 2 c 2 × p 3 c 3 × . . . × p k c k x = p_1^{c_1} \times p_2^{c_2} \times p_3^{c_3} \times...\times p_k^{c_k} x=p1c1×p2c2×p3c3×...×pkck

我们就是要把 c i c_i ci 个 质因子 p i p_i pi 放到 n n n 个位置中。问题转化为: n n n 个盒子放小球的问题,允许存在空盒子

假设有 n n n 个盒子, k k k 个小球。

n n n 个盒子,就有 n − 1 n - 1 n1隔板,加上 k k k 个小球,共有 n − k + 1 n - k + 1 nk+1 个位置。用 n − 1 n - 1 n1 个位置放隔板;用 k k k 个位置放小球;

所以总的方案数为: C n − k + 1 n − 1 C_{n-k + 1}^{n-1} Cnk+1n1 或者 C n − k + 1 k C_{n-k + 1}^{k} Cnk+1k

因为一个元素 x x x 可能有 不同的 若干个质因子,我们采用乘法原理计算。

最终的答案就是 从 i ( 1 ≤ i ≤ m a x V a l u e ) i (1 \leq i \leq maxValue ) i(1imaxValue) 开始,枚举每一个 i i i 的质因数 放到 n n n 个位置中的方案数之和。

时间复杂度:

C++代码:

const int MOD = 1e9 + 7, MX = 1e4 + 1, K = 13; // 因为最多扩大 13 次

 // cnt[x] 为 x 分解质因数后,每个质因数的个数列表
 //比如 x = 12,cnt[x] = {2,1},因为质因子 2 有两个,质因子 3 有一个
vector<int> cnt[MX];

int c[MX + K][K + 1]; // 组合数

//预处理出 2~10000 的质因数列表 以及 组合数
int init = []() {
    
    //求 2~10000 的质因数列表
    for (int i = 2; i < MX; ++i) {
        int x = i;
        for (int p = 2; p * p <= x; ++p) {
            if (x % p == 0) {
                int k = 0;
                while(x % p == 0){
                    k++;
                    x /= p;
                }
                
                cnt[i].push_back(k);
            }
        }
        if (x > 1) cnt[i].push_back(1);
    }

    //求出 C(n -k + 1 , k) , C(n - k + 1,n - 1) 范围内的所有组合数
    c[0][0] = 1;
    for (int i = 1; i < MX + K; ++i) {
        c[i][0] = 1;
        for (int j = 1; j <= min(i, K); ++j)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
    }
    return 0;
}();

class Solution {
public:
    int idealArrays(int n, int maxValue) {
        long long ans = 0LL;
        for (int x = 1; x <= maxValue; ++x) {
            long long mul = 1LL;
            //乘法原理 求x 的每一种质因子 放入n个位置中的方案数
            for (int k: cnt[x]) mul = mul * c[n + k - 1][k] % MOD;
            ans += mul;
        }
        return ans % MOD;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值