lucas定理

介绍

lucas定理用于解决模数p较小的组合数问题

其主要定理有:

lucas(n,m,p)=combin(n%p,m%p)*lucas(n/p.m/p,p)

边界条件为当n<p时return combin(n,m,p)

combin(n,m,p)=n!*(m!*(n-m))^p-2;

题意:

链接:

https://www.luogu.org/problemnew/show/P3807

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,c,d,e,a[500000],b[500000];
ll qsm(ll x,ll y)
{
    if (y==1) return(x);
    if (y%2==0)
    {
        return((ll)(pow(qsm(x,y/2),2))%e);
    } else
    {
        return(((ll)(pow(qsm(x,y/2),2))%e*x)%e);
    }
}
ll combin(ll x,ll y)
{
    if (y>x) return(0);
    return ((a[x]*b[y]) %e*b[x-y])%e;
}
ll lucas(ll x,ll y)
{
    if (x>=e) return (combin(x%e,y%e)*lucas(x/e,y/e))%e;
    else return combin(x,y);
}
int main()
{
    freopen("noip.in","r",stdin);
    freopen("noip.out","w",stdout);
    cin>>n;
    for (ll i=1;i<=n;i++)
    {
        cin>>c>>d>>e; a[0]=b[0]=1; c+=d;
        for (ll j=1;j<=e;j++)
        {
            a[j]=(a[j-1]*j)%e;
          b[j]=qsm(a[j],e-2);
      }
        cout<<lucas(c,d)<<endl;
    }
} 
View Code

 

posted @ 2018-01-02 23:40  尹吴潇  阅读(159)  评论(0编辑  收藏  举报