码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-05-27 19:30:29      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:size   链接   mod   可以转化   ref   href   保存   https   lan   

<题目链接>

题目大意:
用$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定理)

标签:size   链接   mod   可以转化   ref   href   保存   https   lan   

原文地址:https://www.cnblogs.com/00isok/p/10932254.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!