zoukankan      html  css  js  c++  java
  • CF785D Anton and School

    CF785D Anton and School - 2

    题意:给定一个长度(le 2 imes 10e5)由'('和')'组成的字符串,问有多少个子串(可以不连续),前半部分是由('(')组成后半部分由(')')组成.


    考虑枚举每一个可能的字串的中间,然后统计两边

    先预处理每一个位置前面有多少个('('),后面有多少个(')')

    然后枚举每一个('(')表示中间且必选

    设当前位(包括)有(a)('(')
    则对此位置的答案即为(sum_{i=0}^{min(a-1,b-1)} C_{a-1}^i imes C_b^{i+1})

    引理:范德蒙恒等式,(sum_{i=0}^k C_a^i imes C_b^{k-i}=C_{a+b}^k)

    对上式进行化简即可得 (C_{a+b-1}^a)

    预处理阶乘和阶乘逆元即可


    Code:

    #include <cstdio>
    #include <cstring>
    #define ll long long
    const int N=200010;
    const ll mod=1e9+7;
    ll t[N],f1[N],f2[N],fac[N],inv[N],n,ans;
    char c[N];
    ll quick_pow(ll d,ll k)
    {
        ll f=1;
        while(k)
        {
            if(k&1)
                f=f*d%mod;
            d=d*d%mod;
            k>>=1;
        }
        return f;
    }
    ll C(ll a,ll b)
    {
        if(a>b) return 0;
        if(inv[b-a]==-1) inv[b-a]=quick_pow(fac[b-a],mod-2);
        if(inv[a]==-1) inv[a]=quick_pow(fac[a],mod-2);
        return fac[b]*inv[b-a]%mod*inv[a]%mod;
    }
    int main()
    {
        memset(inv,-1,sizeof(inv));
        scanf("%s",c);
        n=strlen(c);
        for(int i=0;i<n;i++)
            t[i+1]=(c[i]==')');
        for(int i=1;i<=n;i++)
            f1[i]=f1[i-1]+!t[i];
        for(int i=n;i;i--)
            f2[i]=f2[i+1]+t[i];
        fac[0]=1;
        for(int i=1;i<=n;i++)
            fac[i]=fac[i-1]*i%mod;
        for(int i=1;i<=n;i++)
            if(!t[i])
            {
                ll a=f1[i],b=f2[i];
                (ans+=C(a,a+b-1))%=mod;
            }
        printf("%lld
    ",ans);
        return 0;
    }
    
    

    2018.7.19

  • 相关阅读:
    bootstrap入门基础
    java遇见的问题分析
    蓝桥杯练习
    win7 在文件夹上右键后 以管理员启动命令窗口
    渲染10万条数据的性能问题
    闲聊一下百度的Unit
    利用c# 多屏显示
    学习Xposed --记WX功能分析的过程
    从零开始打jar包--补充
    修改windows7 的管理员密码
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9338023.html
Copyright © 2011-2022 走看看