【HDU3037】Saving Beans

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3037

题目大意:求在n棵树上摘不超过m颗豆子的方案,结果对p取模。

题解
问题可以转化成求方程 x1+x2++xn=k 的非负整数解的个数,其中 k=0 ~ m
利用插板法,构造yi=xi+1得到新的方程 y1+y2++yn=n+k 的正整数解的个数是 Cn1n+k1 ,即 Ckn+k1
所以现在问题转化为求 mi=0Cin+i1 ,根据组合恒等式 ni=mCmi=Cm+1n+1 (拿杨辉三角随便手玩一下就出来了),易得上式等于 Cnn+m
然后就转化为一个组合数取模的问题,题目中给出p是一个质数,所以直接Lucas就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long

LL fac[100010];

LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    LL ret=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return ret;
}

LL Inv(LL a,LL mod)
{
    LL x,y;
    LL ret=exgcd(a,mod,x,y);
    if(ret==1) return (x%mod+mod)%mod;
    return -1;
}

LL C(int n,int m,int mod)
{
    if(m>n) return 0;
    LL ret=fac[n];
    ret*=Inv((fac[m]*fac[n-m])%mod,mod);
    return ret%mod; 
}

LL Lucas(LL n,LL m,LL mod)
{
    if(m==0) return 1;
    return C(n%mod,m%mod,mod)*Lucas(n/mod,m/mod,mod)%mod;
}

int main()
{
    LL T,a,b,mod;
    fac[0]=1;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld%lld%lld",&a,&b,&mod);
        for(int i=1;i<=mod;i++) fac[i]=(fac[i-1]*i)%mod;
        printf("%lld\n",Lucas(a+b,a,mod));
    }
    return 0;
}

ps:不开long long见祖宗,十年OI一场空

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值