Balanced Subsequences
注意子序列不一定连续。
恰好最长合法括号子序列长度为 \(2k\),那么废掉的 )
个数为 \(m-k\)。
恰好的方案数 \(f_k\) 不好求,我们可以求 \(g_k\) 表示长度至少为 \(2k\) 的方案数。
(
表示向上走,)
表示向下走,\(g_k\) 即为从 \((0,0)\) 走到 \((n+m,n-m)\),且废掉的右括号数 \(-y\le m-k\),即不超过直线 \(y=k-m\)。
\(g_k=\binom{n+m}{n}-\binom{n+m}{k-1}\)。
\(f_k=g_k-g_{k+1}=\binom{n+m}{k}-\binom{n+m}{k-1}\)。
注意判无解 \(k> \min(n,m)\)。
时间复杂度 \(O(n+m)\)。
Code
#include<bits/stdc++.h>
#define sf scanf
#define pf printf
using namespace std;
typedef long long ll;
const int N=2e3+5,mxx=N<<2,mod=1e9+7;
int t;
ll jc[mxx+5],inv[mxx+5];
ll ksm(ll a,ll b){
ll s=1;
while(b){
if(b&1){
s=s*a%mod;
}
a=a*a%mod;
b>>=1;
}
return s;
}
void init(){
jc[0]=1;
for(int i=1;i<=mxx;i++){
jc[i]=jc[i-1]*i%mod;
}
inv[mxx]=ksm(jc[mxx],mod-2);
for(int i=mxx-1;i>=0;i--){
inv[i]=inv[i+1]*(i+1)%mod;
}
}
int n,m,k;
ll C(ll n,ll m){
if(m>n) return 0;
return jc[n]*inv[n-m]%mod*inv[m]%mod;
}
int main(){
init();
sf("%d",&t);
while(t--){
sf("%d%d%d",&n,&m,&k);
if(k>min(n,m)) {
pf("0\n");
continue;
}
pf("%lld\n",(C(n+m,k)-C(n+m,k-1)+mod)%mod);
}
}
标签:return,int,inv,Subsequences,Balanced,binom,ll,mod
From: https://www.cnblogs.com/liyixin0514/p/18468480