HDU---3037:Saving Beans【卢卡斯定理】

本文探讨了HDU-3037题目中将松果分配到多棵树上的组合计数问题,利用插板模型和卢卡斯定理解决大数除法逆元不存在的情况,提供了一种高效求解方案。

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

题目:

HDU - 3037

题意:

把 m 个松果最多分到 n 颗树上,求有多少种分法

分析:

设第 i 颗树上放 Xi 个,无非等价于求解下式解的个数

X_1+X_2+X_3+......+X_k=M

插板模型可得答案为:C_{m+k-1}^{k-1}

而 1 =< k <= n,所以最终答案为:

\sum_{1}^{n}C_{m+k-1}^{k-1}~~(mod~p)

=C_{m}^{0}+C_{m+1}^{1}+C_{m+2}^{2}+......+C_{m+k-1}^{m}

=C_{m+1}^{0}+C_{m+1}^{1}+C_{m+2}^{2}+......+C_{m+k-1}^{m}

=C_{m+2}^{1}+C_{m+2}^{2}+......+C_{m+k-1}^{m}

=C_{m+n}^{m}~~(mod~p)

\frac{(m+n)*(n+m-1)*......*(n+1)}{m!}~~(mod~p)

如果 m < p 可直接求个逆元即可,若m > p,则m!和 p 一定不互质,这就不能求出逆元,这时有个叫卢卡斯的站了起来:

卢卡斯定理:

C_m^n=C_{m~mod~p}^{n~mod~p}*C_{m/p}^{n/p}~~(mod~p)

若 m/p 任然大于 p,递归求解就可

代码:

#include <iostream>
using namespace std;
typedef long long ll;
ll Pow(ll a,ll p)
{
    ll ans = 1;
    ll x = p-2;
    while(x)
    {
        if(x&1) ans = ans*a%p;
        a = a*a%p;
        x>>=1;
    }
    return ans%p;
}
ll cal(ll n,ll m,ll p)
{
    if(m>n) return 0;
    ll res = 1;
    for(int i=n;i>n-m;--i)
        res = res*i%p;
    ll a = 1;
    for(int i=1;i<=m;++i)
        a = a*i%p;
    return res*Pow(a,p)%p;
}
ll Lucas(ll n,ll m,ll p)
{
    if(m<p) return cal(n,m,p);
    else return cal(n%p,m%p) * Lucas(n/p,m/p,p)%p;
}
int main()
{
    ll t,n,m,p;
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>p;
        cout<<Lucas(n+m,m,p)<<endl;
    }
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值