2023/6/19---个人总结

D - Factorization


题目大意:给定n,m。求n个数相乘等于m的方案个数
思路:对m进行质因数分解,求出每一个质因数的个数,分别求出每一个质因数有多少种排列方式,求所有质因数排列方式的乘积即可。把每一个质因数都看成一种小球,有n个盒子,假设一个质因数有a个,即a个相同小球放入n个盒子的问题。隔板法:在a-1个空隙中插入n-1个隔板,结果为C(a-1,n-1)。又因为盒子可以为空(用1补),该问题又变为a+n个小球放入n盒子的问题,最终结果为C(a+n-1,n-1)。由于组合数的计算中有插法运算,而且取模数较大,需要逆元。原因:a除以一个数模p,等于a乘这个数的逆元模p。
求逆元:
费马定理:当a和p满足gcd(a,p)=1,且p为质数,则a的p次方和a同余(a^p===a(mod p)),
即a*a^p-2===1(mod p),用快速幂算出a^p-2,即a的逆元
计算阶乘的逆元:inv[i]=inv[i+1]*(i+1)%mod(先把inv[i+1]算出来)||(inv[i]=(inv[i-1]*power(i,mod-2))%mod)。

计算连续的数的逆元:inv[i]=(p-(p/i))*inv[p%i]%mod。

const ll mod = 1e9 + 7;
ll f[300005];
ll inv[300005];
ll power(ll a, ll b) {   //快速幂算出a的逆元
    ll ans = 1;
    while (b) {
        if (b & 1)
            ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}

void init() {  //初始化把阶乘和阶乘的逆元算出
    inv[0] = inv[1] = f[0] = f[1] = 1;
    for (int i = 2; i <= 3e5+5; i++) {
        f[i] = (i * f[i - 1]) % mod;
        inv[i] = (inv[i - 1] * power(i, mod - 2)) % mod;
    }
}

ll C(int a,int b) {   //计算C(a,b)
    return (f[a] * inv[b] % mod * inv[a - b] % mod) % mod;
}

void solve() {
    int n, m;
    cin >> n >> m;
    init();
    ll ans = 1;
    for (int i = 2; i <= m; i++) {
        if (m % i == 0) {   //唯一分解
            int cnt = 0;
            while (m % i == 0) {
                cnt++;
                m /= i;
            }
            ans = ans * C(cnt + n - 1, n - 1) % mod;
        }
    }
    cout << ans << '\n';
}

要搞课设,复习,今天又要掉分。。。。。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

akb000

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值