Codeforces Round #404 (Div. 2) ---d

D. Anton and School - 2

 

这题第一眼一直觉得是dp,然而到最后他竟然是个数学题2333

考虑暴力,我们枚举一个'(',来求选他的情况下方案数有多少,那么事实上我们就是要在该位置左边选取i个'(',在其右边选取i+1个')',可以保证不重不漏。暴力的话On统计即可。那么就是要化简组合数的求和。即C(n,i)*C(m,i+1) (0<=i<=min(n,m-1))

我们发现C(m,i+1)=C(m,m-i-1)

而i+(m-i-1)是定值。

也就是说变成了现在前n个数中选i个,再在后m个数中选m-1-i个,那么这其实等价于在这n+m个数字中一次性选出m-1个。

那么答案就是C(m+n,m-1),On扫一遍并计算组合数即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int mod=1e9+7;
 4 const int inf=2e5+10;
 5 int fast(int x,int y){
 6     int ans=1;
 7     while(y){
 8         if(y&1)ans=1ll*ans*x%mod;
 9         x=1ll*x*x%mod;
10         y>>=1;
11     }
12     return ans;
13 }
14 int fac[inf];
15 int C(int x,int y){
16     return 1ll*fac[x]*fast(fac[y],mod-2)%mod*fast(fac[x-y],mod-2)%mod;
17 }
18 int n,ans;
19 char s[inf];
20 int s1[inf],s2[inf];
21 int main()
22 {
23     scanf("%s",s+1);
24     n=strlen(s+1);
25     fac[0]=1;
26     for(int i=1;i<=n;i++)
27         fac[i]=1ll*fac[i-1]*i%mod;
28     for(int i=1;i<=n;i++)
29         s1[i]=s1[i-1]+(s[i]=='(');
30     for(int i=n;i>=1;i--)
31         s2[i]=s2[i+1]+(s[i]==')');
32     for(int i=1;i<=n;i++)
33         if(s[i]=='('){
34             ans+=C(s1[i-1]+s2[i+1],s2[i+1]-1);
35             ans%=mod;
36         }
37     printf("%d\n",ans);
38     return 0;
39 }
View Code

 

 

事实上这个就是"范德蒙恒等式"

转载于:https://www.cnblogs.com/hyghb/p/8505451.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值