CodeForces

来源:互联网 发布:金字塔软件回测 编辑:程序博客网 时间:2024/06/05 15:43





http://codeforces.com/problemset/problem/785/D





题目大意:

长度为偶数

左侧全为 '('

右侧全为  ')'

左右长度相同

问满足上述条件的子序列有多少种选法


分析:

首先   范德蒙恒等式         

枚举分界线    每一个分界线记录其左侧 '(' 数量和右侧 ')' 数量(包含本身)   

从左到右   每遇到一个  '('  时    当前 '(' 必选       则其贡献值为              然后根据范德蒙恒等式可得         (以上两图来自QuanQqqqq的博客)



AC代码:

#include <iostream>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include <vector>#include <stack>#include <queue>#include <map>#include <set>#include<list>#include <bitset>#include <climits>#include <algorithm>#define gcd(a,b) __gcd(a,b)#define FINfreopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w",stdout)typedef long long LL;const LL mod=1e9+7;const int INF=0x3f3f3f3f;const double PI=acos(-1.0);using namespace std;struct node{    int l;    int r;}a[2000005];char str[2000005];LL fac[2000005];LL Power(LL a,LL b){    LL temp=1;    while (b){        if(b%2)            temp=(temp*a)%mod;        b/=2;           a=a*a%mod;    }    return temp%mod;}void fun(){    fac[0]=1;    fac[1]=1;    for (int i=2;i<=2000000;i++){        fac[i]=fac[i-1]*i%mod;    }}LL cal(LL n,LL m){    return fac[n]*Power(fac[n-m],mod-2)%mod*Power(fac[m],mod-2)%mod;}int main (){   // FIN;    fun();    while (scanf("%s",str+1)!=EOF){        int n=strlen(str+1);        memset(a,0,sizeof(a));        for (int i=1;i<=n;i++){            if (str[i]=='(')                a[i].l=a[i-1].l+1;            else                a[i].l=a[i-1].l;        }        for (int i=n;i>=1;i--){            if (str[i]==')')                a[i].r=a[i+1].r+1;            else                a[i].r=a[i+1].r;        }        LL ans=0;        for (int i=1;i<=n;i++){            if (str[i]=='('){                ans+=cal(a[i].l+a[i].r,a[i].r);            }        }        printf ("%lld\n",ans%mod);    }    return 0;}


原创粉丝点击