bzoj2982: combination(lucas)

Description

LMZ n 个不同的基友,他每天晚上要选 m 个进行 [ 河蟹 ] ,而且要求每天晚上的选择都不一样。那么 LMZ 能够持续多少个这样的夜晚呢?当然, LMZ 的一年有 10007 天,所以他想知道答案 mod 10007 的值。 (1<=m<=n<=200,000,000)

Input

   第一行一个整数 t ,表示有 t 组数据。 (t<=200)
   接下来 t 行每行两个整数 n, m ,如题意。

Output

T 行,每行一个数,为 C(n, m) mod 10007 的答案。

思路:

不想说什么,标准的lucas,比luogu上的板子还简单

lucas大家应该都知道,不知道的可以看我的博客(抱歉啊,还有bug,没发布)

核心代码就一行:

(lucas(s/p,t/p)*zhs(s%p,t%p))%p

重点在预处理逆元

代码:

#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,p,t,ny[100005];
void qny()
{
	ny[1]=1;
	for(register int a=2;a<=p-1;a++)
	{
		ny[a]=(p-(p/a))*ny[p%a]%p;
	}
}
int zhs(int q,int x)
{
	if(q==0)
	{
		return 1;
	}
	long long ltt=1;
	for(register int a=1;a<=q;a++)
	{
		ltt*=ny[a];
		ltt%=p;
	}
	for(register int a=1;a<=q;a++)
	{
		ltt*=(x-a+1);
		ltt%=p;
	}
	return ltt;
}
long long lucas(int s,int t)
{
	if(t==0)
	{
		return 1;
	}
	else
	{
		return (lucas(s/p,t/p)*zhs(s%p,t%p))%p;
	}
}
int main()
{
	scanf("%d",&t);
	p=10007;
	qny();
	for(int i=1;i<=t;i++)
	{
		scanf("%d%d",&n,&m);
		printf("%lld\n",lucas(m,n));
	}
}

  

猜你喜欢

转载自www.cnblogs.com/ztz11/p/9158907.html
今日推荐