zoukankan      html  css  js  c++  java
  • [CF893E] Counting Arrays

    [CF893E] Counting Arrays - 组合计数

    Description

    给出x和y,求一个长度为y的序列,其乘积为x,允许有负数,求这种序列的个数,对1e9+7取模。

    Solution

    其实就是分配质因子,而且每个质因子还是独立的

    先考虑绝对值

    单独考虑每个质因子的分配,假设有 q 个,我们要分配给 n 个位置,每个位置非负整数

    这样的方案数用隔板法算,先变成 n+q 个,然后在 n+q-1 个间隔中选 n-1 个放隔板,即 C(n+q-1,n-1)

    不同的质因子之间,方案数通过乘法原理乘在一起

    至于符号,额外乘个枚举子集的方案数即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int mod = 1e9 + 7;
    
    namespace math_mod
    {
        int c__[5005][5005], fac__[3000005];
    
        int qpow(int p, int q)
        {
            return (q & 1 ? p : 1) * (q ? qpow(p * p % mod, q / 2) : 1) % mod;
        }
    
        int inv(int p)
        {
            return qpow(p, mod - 2);
        }
    
        int fac(int p)
        {
            if (p <= 3000000)
                return fac__[p];
            if (p == 0)
                return 1;
            return p * fac(p - 1) % mod;
        }
    
        int __fac(int p)
        {
            return fac(p);
        }
    
        int ncr(int n, int r)
        {
            if (r < 0 || r > n)
                return 0;
            return fac(n) * inv(fac(r)) % mod * inv(fac(n - r)) % mod;
        }
    
        void math_presolve()
        {
            fac__[0] = 1;
            for (int i = 1; i <= 3000000; i++)
            {
                fac__[i] = fac__[i - 1] * i % mod;
            }
            for (int i = 0; i <= 5000; i++)
            {
                c__[i][0] = c__[i][i] = 1;
                for (int j = 1; j < i; j++)
                    c__[i][j] = c__[i - 1][j] + c__[i - 1][j - 1], c__[i][j] %= mod;
            }
        }
    
        int __c(int n, int r)
        {
            if (r < 0 || r > n)
                return 0;
            if (n > 5000)
                return ncr(n, r);
            return c__[n][r];
        }
    }
    
    using namespace math_mod;
    
    void solve()
    {
        int m, n;
        cin >> m >> n;
    
        int ans = 1;
        int tmp = m;
        for (int i = 2; i * i <= m; i++)
        {
            int q = 0;
            while (tmp % i == 0)
            {
                tmp /= i;
                q++;
            }
            if (q)
            {
                ans *= __c(n + q - 1, q);
                ans %= mod;
            }
        }
        if (tmp > 1)
        {
            int q = 1;
            ans *= __c(n + q - 1, q);
            ans %= mod;
        }
        cout << ans * qpow(2, n - 1) % mod << endl;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        math_presolve();
    
        int t;
        cin >> t;
    
        while (t--)
        {
            solve();
        }
    }
    
  • 相关阅读:
    xutils3批量上传文件
    超详细Android面试的准备与经历分享 | 百度(offer)
    [网站公告]3月10日23:00-4:00阿里云SLB升级,会有4-8次连接闪断团队
    上周热点回顾(3.2-3.8)团队
    发布新博客皮肤red_autumnal_leaves团队
    上周热点回顾(2.23-3.1)团队
    上周热点回顾(2.16-2.22)团队
    上周热点回顾(2.2-2.8)团队
    如何禁止IE自动生成链接团队
    [云上天气预报-有时有闪电]2月3日23:00-4:00阿里云SLB升级期间网络会闪断团队
  • 原文地址:https://www.cnblogs.com/mollnn/p/14485235.html
Copyright © 2011-2022 走看看