hdu3037(卢卡斯定理+组合数取模)

题目
题意:松鼠要过冬,然后要在n棵树上存不超过m个果子。求有多少种存法。

思路:一共有n棵树,每棵树上有 xi 个果子,问题就可以抽象成 x1+x2+....+xn=m 这样一个等式。而且 xi 是可以为0的。
这样的话就可以写成n个0和m个1写在一行,然后用插板法求解。
但是只是普通的插板法只能解决所有果子都放到树上的情况,所以我们这里人为的添加一个板子,一定是放在最右边的,然后用来记放在地上的果子,这样的话有n+m个空(最左边0的左边也是可以插板子的,代表一棵树上不放果子,是一样的),n个板子,然后答案就是 C (nn+m).但是这里的n和m特别大,然而要取模的mod比较小,所以要用卢卡斯定理

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int fcnt=100101;
long long mod,p;
long long fac[fcnt];
void getfac(int mo)
{
    fac[0]=1;
    for(int i=1;i<=mo;i++)
        fac[i]=fac[i-1]*i%mod;
}
long long quickpow(long long a,long long b)
{
    if(b<0)return 0;
    long long ret=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            ret=(ret*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return ret;
}
long long inv(long long a)
{
    return quickpow(a,mod-2);
}
long long c(long long n,long long m)
{
    if(n<m)
        return 0;
    return fac[n]*inv(fac[m])%mod*inv(fac[n-m])%mod;
}
long long Lucas(long long n,long long m)
{
    if(m==0)
        return 1;
    return Lucas(n/p,m/p)*c(n%p,m%p)%p;
}
int main()
{
    int t;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            long long int t1,t2;
            scanf("%lld %lld %lld",&t1,&t2,&p);
            mod=p;
            getfac(p);
            long long ans=Lucas(t1+t2,t1);
            printf("%lld\n",ans);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值