To_Heart—题解——HDU3037

更好的阅读体验

题目

Saving Beans

题意

不超过 m 个球放入 n 个盒子方案数,盒子可以为空。

题解

然后我们发现它要求的是不超过 m 个球,并不是一个定值,不好算,所以我们考虑再给他一个盒子,在前面的盒子里面放 k 个,就在最后的盒子里面放 m-k 个,这样问题就转换成了:

m 个球放入 n+1 个盒子方案数,盒子可以为空。

然后用隔板法求出方案数为 ( n + m + 1 − 1 m ) = ( n + m m ) \dbinom{n+m+1-1}{m}=\dbinom{n+m}{m} (mn+m+11)=(mn+m)

然后注意到这道题目的 n,m 范围很大,但模数很小,所以考虑使用 Lucas定理。

然后就做完了。

代码

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

ll fac[2000005];
ll inv[2000005];

ll n,m,Mod;

ll Pow(ll a,ll b){
    
    
    ll ans=1;
    while(b){
    
    
        if(b&1) ans*=a,ans%=Mod;
        a*=a,a%=Mod,b>>=1;
    }
    return ans;
}


void Init(int N){
    
    
    fac[0]=1;for(ll i=1;i<=N;i++) fac[i]=fac[i-1]*i%Mod;
}

ll Lucas(ll n,ll m){
    
    
    if(!m) return 1ll;
    ll x=n%Mod;
    ll y=m%Mod;
    if(y>x) return 0ll;
    ll now=fac[x]*Pow(fac[y],Mod-2)%Mod*Pow(fac[x-y],Mod-2)%Mod;
    return now*Lucas(n/Mod,m/Mod)%Mod;
}

int main(){
    
    
    int T;cin>>T;
    while(T--){
    
    
        scanf("%lld%lld%lld",&n,&m,&Mod);
        Init(Mod+1);
        printf("%lld\n",Lucas(n+m,m));
    }
    
}

Supongo que te gusta

Origin blog.csdn.net/xf2056188203/article/details/121568603
Recomendado
Clasificación