HDU 3037 Saving Beans (隔板法+Lucas定理)

Posted 00isok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3037 Saving Beans (隔板法+Lucas定理)相关的知识,希望对你有一定的参考价值。

<题目链接>

题目大意:
用$n$颗树保存不超过$m$颗豆子($n,m\leq10^9$)(不一定所有的树都有豆子保存),问你总共有多少种情况。答案对p取模(p保证是个素数)。


解题分析:
可以转化成 将$n$个相同的球放入$m$个集合中,有的集合中的球数可能为0的等价问题。
很明显这可以用隔板法解决,答案为$C(n+m-1,m-1)$
则题目解的个数可以转换成求: $C(n+m-1,0)+C(n+m-1,1)+C(n+m-1,2)+……+C(n+m-1,m-1)$

利用组合数公式 $C(n,k) = C(n-1,k)+C(n-1,k-1)$。将上式转化为$C(n+m,m)%p$。

现在就是要求 $C(n+m,m)%p$。

因为n,m很大,并且p是质数,直接用Lucas定理求解即可。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5+100;
ll fac[N],mod;

inline void init(){
    fac[0]=1;
    for(int i=1;i<=mod;i++)
        fac[i]=fac[i-1]*i%mod;
}

ll ksm(ll a,ll b){
    ll ans=1;a%=mod;
    while(b){
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }return ans;
}
ll C(ll n,ll m){      
    if(m>n)return 0;
    return fac[n]*(ksm(fac[m]*fac[n-m]%mod,mod-2))%mod;   //费马小定理求逆元
}
ll Lucas(ll n,ll m){
    if(m==0)return 1;
    return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
}
int main(){
    ll n,m,T;cin>>T;
    while(T--){
        cin>>n>>m>>mod;
        init();
        cout<<Lucas(n+m,m)<<endl;
    }    
}

 



以上是关于HDU 3037 Saving Beans (隔板法+Lucas定理)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3037 Saving Beans

hdu 3037 Saving Beans

HDU 3037:Saving Beans

HDU3037Saving Beans(组合数+lucas定理)

hdu 3037Saving Beans(卢卡斯定理)

J - Saving Beans (HDU - 3037)