• hdu3037 Silver Cow Party (Lucas定理 组合数取模)


    题意为:将不超过m个豆子放在n棵不同的树上,一共有多少种方法。

    题目相当于求n个数的和不超过m的方案数。

    如果和恰好等于m,那么就等价于方程x1+x2+...+xn = m的解的个数,利用插板法可以得到方案数为:

    (m+1)*(m+2)...(m+n-1)  = C(m+n-1,n-1) = C(m+n-1,m)

    现在就需要求不大于m的,相当于对i = 0,1...,m对C(n+i-1,i)求和,根据公式C(n,k) = C(n-1,k)+C(n-1,k-1)得

    C(n-1,0)+C(n,1)+...+C(n+m-1,m)

    = C(n,0)+C(n,1)+C(n+1,2)+...+C(n+m-1,m)

    = C(n+m,m)

    现在就是要求C(n+m,m) % p,其中p是素数。

    然后利用Lucas定理的模板就可以轻松的求得C(n+m,m) % p的值

     

    代码:

    #include <iostream>
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=100002;
    
    int T;
    ll fact[maxn];
    ll n,m,p;
    
    void F(ll p)
    {
        fact[0]=1;
        for(int i=1;i<=p;i++)
            fact[i]=fact[i-1]*i%p;
    }
    
    ll qpow_mod(ll a,ll n,ll b)
    {
        ll s=1;
        while(n)
        {
            if(n&1)
                s=s*a%p;
            a=a*a%p;
            n>>=1;
        }
        return s;
    }
    
    ll Lucas(ll n,ll m,ll p)
    {
        ll ans=1;
        while(n&&m)
        {
            ll a=n%p;
            ll b=m%p;
            if(a<b) return 0;
            ans=(ans*fact[a]*qpow_mod(fact[b]*fact[a-b]%p,p-2,p))%p;
            n/=p;
            m/=p;
        }
        return ans;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>T;
        while(T--)
        {
            cin>>n>>m>>p;
            F(p);
            cout<<Lucas(n+m,m,p)<<endl;
    
        }
        return 0;
    }
  • 相关阅读:
    懒人的gitlab安装
    SuperFish插件实现鼠标停留浮动的菜单栏.
    Bootstrap I
    京东首页样式分析.
    CentOs装VLC
    TI CC2541的通讯抓包.
    ffmpeg+ffserver实现摄像头直播
    arm linux上的第一个应用程序 BOA移植
    linux内核移植 I
    uboot启动参数
  • 原文地址:https://www.cnblogs.com/Fy1999/p/9149796.html
Copyright © 2020-2023  润新知