件名:https :
//ac.nowcoder.com/acm/problem/15077
スタックが空でないときに新しい要素をプッシュしたり、要素をポップしたりできるたびに、nnn個の要素を順番に積み重ねる必要があり、WYF WYFW Y Fは、mmm個の要素がスタックに配置された後、スタックにkkが発生しますk個の要素があり、スタックとアンスタックの順序がこの条件を満たす数を知りたいと考えています。
アイデア:
最初に2つのサブ問題に分けます
- ではミリメートルm個の要素がスタックに配置される前に、m − 1m-1があります。m−1スタック、m − k mkm−kポップ、各瞬間のプッシュ数がポップ数以上の場合、計画は
(2 m − 1 − km − 1)km {2m-1-k \ choice m-1} \ frac {k} {m}((m−12メートル−1−K)mK - ではミリメートルm個の要素を積み重ねた後、n −mnmがありますn−Mスタックに、N - N-M + K M + Kn−m+kがポップし、ポップの数から各瞬間のプッシュの数を引いたものがkk以下であるk(スタックにはすでにkkがありますk要素)、スキームの数は
(2 n − 2 m + kn − m)k + 1 n − m + k + 1 {2n-2m + k \ choice nm} \ frac {k + 1} {n-m + k + 1}((n−m2 n−2メートル+K)n−m+k+1k+1
答えは乗算です
注:組み合わせの数を計算する際に違法な状況があります
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
const int N=4000009;
int T;
ll p[N],p1[N];
ll qpow(ll a, ll b){
ll res=1;
a%=mod;
while(b){
if(b&1)
res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll cal(ll a,ll b){
if(a<0||b<0||a-b<0)//不合法
return 0;
return p[a]*p1[b]%mod*p1[a-b]%mod;
}
int main() {
p[0]=1;
for(int i=1;i<N;i++)
p[i]=p[i-1]*i%mod;
p1[N-1]=qpow(p[N-1],mod-2);
for(int i=N-2;i>=0;i--)
p1[i]=p1[i+1]*(i+1)%mod;
cin>>T;
while(T--){
ll n,m,k,tmp,tmp1;
cin>>n>>m>>k;
tmp=cal(2*m-1-k,m-1)*k%mod*qpow(m,mod-2)%mod;
tmp1=cal(2*n-2*m+k,n-m)*(k+1)%mod*qpow(n-m+k+1,mod-2)%mod;
cout<<tmp*tmp1%mod<<endl;
}
return 0;
}