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
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<

 

你可能感兴趣的:(数论)