codeforces 785D. Anton and School

来源:互联网 发布:sso算法 编辑:程序博客网 时间:2024/05/07 12:28

Problem Link

D. Anton and School - 2
这里写图片描述

分析

官方题解已经写的很好了,不过我有点不理解它的证明,我,即他说的那个一一对应的那部分,
这里写图片描述
想一下如果上图31的位置刚好在左括号的位置这样不就没有匹配了吗?不知道是不是我英文不好的原因23333
不过我们如果限定了最后一个开括号的位置就会很容易给定在这种情况一定是对应着(x+y1x).
按照它的思想有xyx1y0010,那么剩下的位置的排列中由于1x0因此必定有一个1与右括号对应这样就不会出现所有的1与左括号对应的情况了。后面就是按照他的思想来计算了.

AC code

#include <cstdio>#include <algorithm>#include <cstring>#include <string>#include <iostream>#include <vector>#include <queue>#include <map>#include <set>#include <bitset>#include <cmath>#define INF 0x3f3f3f3f#define fi first#define se secondusing namespace std;typedef pair<int,int> Pair;typedef long long LL;const int maxn = 2e5+10;const int MOD = 1e9+7;LL fact[maxn];LL power_inv(LL x,LL n){  LL res =1 ;  while (n) {    if(n&1)res = res*x%MOD;    x = x*x%MOD;    n>>=1;  }  return res;}void init(){  fact[0] = 1;  for(int i=1 ; i<maxn ; ++i)fact[i] = fact[i-1]*i%MOD;}LL Comb(int m,int n){  LL a = (power_inv(fact[n],MOD-2)*power_inv(fact[m-n],MOD-2)%MOD);  return fact[m]*a%MOD;}int pre_sum[maxn];string s;int main(){  init();  cin>>s;  pre_sum[0] = s[0] =='(';  for(int i=1 ; i<s.size() ; ++i)    pre_sum[i] = pre_sum[i-1]+(s[i] == '(');  LL ans = 0;  for(int i = 0 ; i<s.size() ; ++i){    if(s[i]!='(')continue;    int x = pre_sum[i];    int y = s.size()-pre_sum[s.size()-1]-(i+1-pre_sum[i]);    ans+=Comb(x+y-1,x);    ans%=MOD;  }  std::cout << ans << '\n';  return 0;}

总结

组合数取模 问题,当时没想到预处理于模逆的公式。

0 0