卢卡斯定理

卢卡斯定理是用来求组合数取模的一种log级别的算法。

Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)

至于组合数怎么求可以参考逆元博客。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

#define ll long long
#define il inline
#define db double

using namespace std;

int k,n,m,p;
ll a[100045],b[100045];
ll luca(int x,int y)
{
  if(x<y)
    return 0;
  else
    if(x<p)
      return b[x]*a[y]*a[x-y]%p;
    else
      return luca(x/p,y/p)*luca(x%p,y%p)%p;
}

int main()
{
  scanf("%d",&k);
  for(int i=1;i<=k;i++)
    {
      scanf("%d%d%d",&n,&m,&p);
      a[0]=a[1]=b[0]=b[1]=1;
      for(int i=2;i<=n+m;i++)
	a[i]=(p-p/i)*a[p%i]%p,b[i]=b[i-1]*i%p;
      for(int i=2;i<=n+m;i++)
	a[i]=a[i-1]*a[i]%p;
      printf("%lld\n",luca(n+m,m));
    }
  return 0;
}

 

posted @ 2018-10-24 20:50  GSHDYJZ  阅读(205)  评论(0编辑  收藏  举报