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定理)的主要内容,如果未能解决你的问题,请参考以下文章