Skip to main content
  1. Posts/

LeetCode-2338 统计理想数组的数目

·2 mins·

LeetCode-2338 统计理想数组的数目 #

Solution 1 #

该解法来自0x3F大神的题解. 按末尾数字考虑理想数组 $a$ , 假设末尾是 $k$ 考虑数组相邻位的变化, 把 $a_0$ 视作从 $1$ 变化得到, 经过 $n$ 个位置的变化刚好获得 $k$ , 则以 $k$ 为结尾的数组个数即是把 $k$ 的因子分配到 $n$ 个位置的方法. 对于出现了 $c$ 次的因子 $p$ , 采用隔板法可以计算出次数, 按因子相乘再按末尾元素相加得到最终答案. 代码如下:

const int MOD = 1e9 + 7, MX = 1e4 + 1, MX_K = 13; // 至多 13 个质因数
vector<int> ks[MX]; // ks[x] 为 x 分解质因数后,每个质因数的个数列表
int c[MX + MX_K][MX_K + 1]; // 组合数

int init = []() { // 预处理
    for (int i = 2; i < MX; ++i) {
        int x = i;
        for (int p = 2; p * p <= x; ++p) {
            if (x % p == 0) {
                int k = 1;
                for (x /= p; x % p == 0; x /= p) ++k;
                ks[i].push_back(k); // 计算出可能末尾元素的因子个数
            }
        }
        if (x > 1) ks[i].push_back(1);
    }

    // 递推计算组合数
    c[0][0] = 1;
    for (int i = 1; i < MX + MX_K; ++i) {
        c[i][0] = 1;
        for (int j = 1; j <= min(i, MX_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 ans = 0L;
        for (int x = 1; x <= maxValue; ++x) {
            long mul = 1L;
            for (int k: ks[x]) mul = mul * c[n + k - 1][k] % MOD;
            ans += mul;
        }
        return ans % MOD;
    }
};