第一次觉得自己组合数学还可以,也可能是题目太明显了
大致题意:有n个房间,每个房间里面都有1个人,然后发生了k次移动,问现在可能的情况有多少。
先思考,在k次移动后,可能会出现多少个房间的人数为0,很显然,房间人数为0的房间个数的取值范围是[0,min(k,n)]。
再思考,在有 i 个房间人数为0后,就需要把这 i 个人分配到 n-i 个房间中,所以问题就变成了:把 i 个人分配到 n-i 个房间中,那么这个就是组合数学的经典问题:把m个球放到n个盒子中,盒子不同,盒子可以为空,所以 公式:。
就是组合数学里面求组合 就是 C……的公式,不会打。。
所以,总体写法:枚举0的个数 i,同时计算从n个房间选 i 个房间的组合数c1,再去计算 上面的式子c2。最后结果是:
最后,代码:
#include
using namespace std;
const int mod=1e9+7;
const int maxn=2e5+100;
long long int fac[maxn];
void init()
{
fac[0]=1;
for(int i=1;i<=200000;++i)
{
fac[i]=fac[i-1]*i%mod;
}
}
long long int quick_pow(int n,long long int base)
{
long long int ans=1;
while(n)
{
if(n&1)
{
ans*=base;
ans%=mod;
}
base*=base;
base%=mod;
n>>=1;
}
return ans;
}
long long int C(int a,int b)
{
long long int fz=fac[b];
long long int fm=fac[a]*fac[b-a]%mod;
return fz*quick_pow(mod-2,fm)%mod;
}
int main()
{
int n,k;
init();
cin>>n>>k;
k=min(n-1,k);
long long int ans=1;
if(k==1)
ans=0;
for(int i=1; i<=k; ++i)
{
ans+=C(i,n)*C(n-i-1,n-1)%mod;
//cout<