您的位置:首页 > 其它

[ZOJ3557]How Many Sets II(组合数学Lucas定理)

2017-01-15 09:12 537 查看

题目描述

传送门

题意:从n个小球中取m个小球,不能取相邻的小球的方案数

题解

ZOJ的题号到底是什么鬼畜…

这道题是插板法的经典应用

首先我们拿出m个小球,还剩下n-m个小球。这n-m个小球一共有n-m+1个空(左右两边也可以),把这m个小球插入到这n-m+1个空里就是答案,即Cmn−m+1

这m个小球的编号取决于它插入的位置,所以和选哪个小球没关系

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long

LL n,m,Mod;

LL fast_pow(LL a,LL p)
{
LL ans=1LL;
for (;p;p>>=1,a=a*a%Mod)
if (p&1)
ans=ans*a%Mod;
return ans;
}
LL inv(LL x)
{
return fast_pow(x,Mod-2);
}
LL C(LL n,LL m)
{
if (m>n) return 0LL;
LL up=1LL,down=1LL;
for (LL i=n-m+1;i<=n;++i) up=up*i%Mod;
for (LL i=1;i<=m;++i) down=down*i%Mod;
return up*inv(down)%Mod;
}
LL lucas(LL n,LL m)
{
if (m>n) return 0LL;
LL ans=1;
for (;m;n/=Mod,m/=Mod)
ans=ans*C(n%Mod,m%Mod)%Mod;
return ans;
}
int main()
{
while (~scanf("%lld%lld%lld",&n,&m,&Mod))
printf("%lld\n",lucas(n-m+1,m));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: