How Many Sets II 组合数学

3 篇文章 0 订阅

How Many Sets II 组合数学
Time Limit: 2 Seconds Memory Limit: 65536 KB

Given a set S = {1, 2, …, n}, number m and p, your job is to count how many set T satisfies the following condition:

T is a subset of S
|T| = m
T does not contain continuous numbers, that is to say x and x+1 can not both in T

Input

There are multiple cases, each contains 3 integers n ( 1 <= n <= 109 ), m ( 0 <= m <= 104, m <= n ) and p ( p is prime, 1 <= p <= 109 ) in one line seperated by a single space, proceed to the end of file.
Output

Output the total number mod p.
Sample Input

5 1 11
5 2 11

Sample Output

5
6

Author: QU, Zhe
Contest: ZOJ Monthly, October 2011

  • lucas+隔板法
  • 要求在长度为n的串中取 m 个互不相连的数 的取法
  • 我们可以隔板法考虑 取出m个小球 剩下n-m个小球 共n-m+1个地方可以选择插入小球 所以ans-> C(n-m+1,c)
  • Lucas(n, m) = Lucas(n / p, m / p) * C(n % p, m % p) % p
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll pow(ll a,ll b,ll m)
{
	ll ans=1;
	a%=m;
	while(b)
	{
		if(b&1) ans=(ans%m)*(a%m)%m;
		b/=2;
		a=(a%m)*(a%m)%m;
		
	}
	ans%=m;
	return ans;
}
ll inv(ll x,ll p)
{
	return pow(x,p-2,p);
} 
ll C(ll n,ll m,ll p)
{
	if(m>n) return 0;
	ll up=1,down=1;
	for(int i=n-m+1;i<=n;i++) up=up*i%p;
	for(int i=1;i<=m;i++ ) down=down*i%p;
	return up*inv(down,p)%p; 
} 
ll lucas(ll n,ll m, ll p)
{
	if(m==0) return 1;
	return C(n%p,m%p,p)*lucas(n/p,m/p,p)%p;
}
int main()
{
	ll n,m,p;
	while(~scanf("%lld%lld%lld",&n,&m,&p))
	{
		printf("%lld\n",lucas(n-m+1,m,p));
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值