AtCoder Contest 156 E - Roaming

第一次觉得自己组合数学还可以,也可能是题目太明显了

大致题意:有n个房间,每个房间里面都有1个人,然后发生了k次移动,问现在可能的情况有多少。

先思考,在k次移动后,可能会出现多少个房间的人数为0,很显然,房间人数为0的房间个数的取值范围是[0,min(k,n)]。

再思考,在有 i 个房间人数为0后,就需要把这 i 个人分配到 n-i 个房间中,所以问题就变成了:把 i 个人分配到 n-i 个房间中,那么这个就是组合数学的经典问题:把m个球放到n个盒子中,盒子不同,盒子可以为空,所以 公式:\binom{n-1}{n-i-1}

就是组合数学里面求组合 就是 C……的公式,不会打。。

所以,总体写法:枚举0的个数 i,同时计算从n个房间选 i 个房间的组合数c1,再去计算 上面的式子c2。最后结果是:

                                                                         \sum c1*c2

最后,代码:

#include<bits/stdc++.h>
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<<C(i,n)<<" "<<quick_pow(i,n-i)<<" "<<endl;
        ans%=mod;
    }
    cout<<ans<<endl;
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值