题解【[JDWOI-2] 括号串】
首先很明显的,最多匹配的括号对数就是
如果
如果 '(' 或者 ')' 的方案数。因为此处左右括号对称,所以插入左、右括号的方案数相等。此处我们仅以插入右括号为例。
先抛结论:
记 '(' 为 ')' 为
大概证明:
如果在
所以说,我们现在要求出对于
我们考虑对于每一个
把这些位全都加起来,这样的位置总个数是
这样所有值都能
下面是 std (by kouylan)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 4e6;
int Q,M,n,ans,fac[4000005],inv[4000005],cat[4000005],inv1[4000005];
int ksm(int x,int w)
{
int s=1;
while(w)
{
if(w&1)
s = s*x%M;
x = x*x%M;
w >>= 1;
}
return s;
}
signed main()
{
cin>>Q>>M;
fac[0] = 1;
for(int i=1;i<=N+2;fac[i]=fac[i-1]*i%M,i++);
inv[N+2] = ksm(fac[N+2],M-2);
for(int i=N+1;i>=1;i--)
inv[i] = inv[i+1]*(i+1)%M;
inv[0] = 1;
inv1[1] = 1;
for(int i=2;i<=N+2;i++)
inv1[i] = M-M/i*inv1[M%i]%M;
cat[1] = 1;
for(int i=2;i<=N/2;i++)
cat[i] = cat[i-1]*(4*i-2)%M*inv1[i+1]%M;
while(Q--)
{
scanf("%lld",&n);
if(n==1)
{
puts("2");
continue;
}
int m=n/2;
if(n%2==0)
printf("%lld\n",cat[m]);
else
printf("%lld\n",2*cat[m+1]%M);
}
return 0;
}
祝大家 AC 愉快!