Codeforces-785D-Anton and School - 2(组合数学,范德蒙恒等式)

题目链接:Codeforces-785D-Anton and School - 2

每当扫描到一个左括号时,设这个左括号必选,左边有 a 个左括号(包括其本身),右边有 b 个右括号,那么有 min(a1,b1)i=0Cia1Ci+1b 种方案,那么答案应该是所有左括号的方案之和。根据范德蒙恒等式 Cka+b=ki=0CkiaCib (很容易看出这个公式的含义,因此不证了),我们可以简化一下上面那个求和式。

min(a1,b1)i=0Cia1Ci+1b=min(a1,b1)i=0Ca(i+1)a1Ci+1b=Cb1a+b1=min(a,b)i=0Caia1Cib=Caa+b1

因此,无论求和的上标取 a 还是 b ,答案都与最右边的表达式相等。
因此可以 O(nlog(mod)) 预处理出阶乘和阶乘的逆元,然后 O(n) 算出答案。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
const ll mod=1e9+7;
ll fac[maxn],inv[maxn];
ll QMult(ll a, ll b)
{
    ll c=1;
    while(b)
    {
        if(b&1) c=c*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return c;
}
void init()
{
    fac[0]=inv[0]=1;
    for(ll i=1;i<maxn;i++)
    {
        fac[i]=fac[i-1]*i%mod;
        inv[i]=QMult(fac[i],mod-2);
    }
}
ll C(ll m, ll n)
{
    return fac[n]*inv[n-m]%mod*inv[m]%mod;
}
int main()
{
    ios::sync_with_stdio(false);
    init();
    string s;
    cin>>s;
    int r=0,l=0;
    for(int i=0;i<s.length();i++)
        if(s[i]==')') r++;
    ll ans=0;
    for(int i=0;i<s.length();i++)
    {
        if(s[i]=='(') l++;
        else r--;
        if(s[i]=='(') ans=(ans+C(l,l+r-1))%mod;
    }
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值