2018年长沙理工大学第十三届程序设计竞赛 J题 杯子

链接:https://www.nowcoder.com/acm/contest/96/J
来源:牛客网

杯子
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

一天durong同学买了一个无限长的杯子,同时买了n个球,并且标号为1,2,3......n,durong同学突然想到一个问题----如果他把n个球依次,也就是按照1,2,3...n的顺序放进杯子里,然后在全部拿出来(注意不一定要等到全部放进去才能拿出球),并且会记录放进和拿出球的顺序,
durong想知道,要满足当第m个球进去后,杯子中此时恰好有k个球,然后仍然要把剩下的n-m个球放进去,最后杯中的球要取光,这样的放进和拿出球的顺序有多少种,答案有可能很大,所以mod上1e9+7

输入描述:

1<=n,m,k<=1e6(m可能大于n,k可能大于m)
第一行一个正整数T,表示数据组数。(1<=T<=10000)
对于每组数据包含一行三个正整数n,m,k。

输出描述:

对于每组数据输出一个正整数表示答案。
由于答案可能过大,所以只需要输出对1e9+7取模后的答案
示例1

输入

2
3 3 3
3 3 2

输出

1
2

这题的杯子其实就是一个栈。要我们求的答案数量由两部分组成,就叫A和B吧,A部分表示在栈放了m个数之后,里面剩了k个数的方案数,由于题目说了刚刚放入第m个数,因此栈顶的元素是第m个数,是确定的,因此A部分是放了m-1个数,里面剩了k-1个数的方案数。B部分是栈中已经有了k个数,再放入n-m个数,然后全部取完的方案数。因此代码如下

#include<cstdio>
#define maxn 4000000
const int mod=1e9+7;
typedef long long ll;
int F[maxn];
void init(){
    F[0]=1;
    for(int i=1;i<maxn;i++){
        F[i]=(ll)F[i-1]*i%mod;
    }
}
int powermi(int a,int n){
    a%=mod;
    int res=1;
    while(n){
        if(n&1)res=((ll)res*a)%mod;
        a=((ll)a*a)%mod;
        n>>=1;
    }
    return res;
}
int niyuan(int k){
    return powermi(k,mod-2);
}
int c(int n,int m){
    return (int)(((ll)F[n]*niyuan(F[n-m])%mod)*niyuan(F[m])%mod);
}
int cal(int i,int j){
    int k=(ll)c(2*i+j,i)*(j+1)%mod;
    k=(ll)k*niyuan(i+j+1)%mod;
    return k;
}
int cal2(int n,int m,int k){
    if(m-k==0)return 1;
    int t=(ll)c(2*m-k-1,m-k)*niyuan(m)%mod;
//    printf("%d\n", t);
    t=(ll)t*k%mod;
    return t;
 //   return ((c(2 * m - k - 1, m - k) -c(2 * m - k - 1, m - k - 1)) % mod + mod) % mod;;
}
int main(){
    init();
    int T,n,m,k;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        int i=n-m,j=k;
        if(m>n||k>m)printf("0\n");
        else printf("%d\n",(int)((ll)cal(i,j)*cal2(n,m,k)%mod));
    }
    return 0;
}

阅读更多

没有更多推荐了,返回首页