作る

件名:https
//ac.nowcoder.com/acm/problem/15077

スタックが空でないときに新しい要素をプッシュしたり、要素をポップしたりできるたびに、nnn個の要素を順番に積み重ねる必要があり、WYF WYFW Y Fは、mmm個の要素がスタックに配置された、スタックにkkが発生しますk個の要素があり、スタックとアンスタックの順序がこの条件を満たす数を知りたいと考えています。

アイデア:
最初に2つのサブ問題に分けます

  • ではミリメートルm個の要素がスタックに配置される前に、m − 1m-1があります。m1スタック、m − k mkmkポップ、各瞬間のプッシュ数がポップ数以上の場合、計画は
    (2 m − 1 − km − 1)km {2m-1-k \ choice m-1} \ frac {k} {m}((m12メートル1KmK
  • ではミリメートルm個の要素を積み重ねたn −mnmがありますnMスタックに、N - N-M + K M + Knm+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}((nm2 n2メートル+Knm+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;
}

おすすめ

転載: blog.csdn.net/qq_43520313/article/details/109211081