Codeforces 785D - Anton and School - 2 - [範德蒙德恆等式][快速冪+逆元]

題目連接:https://codeforces.com/problemset/problem/785/Dc++

 

題解:算法

首先很好想的,若是咱們預處理出每一個 "(" 的左邊還有 $x$ 個 "(",以及右邊有 $y$ 個 ")",那麼就有式子以下:優化

  ① 若 $x+1 \le y$:$C_{x}^{0} C_{y}^{1} + C_{x}^{1} C_{y}^{2} + \cdots + C_{x}^{x} C_{y}^{x+1} = \sum_{i=0}^{x} C_{x}^{i} C_{y}^{i+1}$spa

  ② 若 $x+1 > y$:$C_{x}^{0} C_{y}^{1} + C_{x}^{1} C_{y}^{2} + \cdots + C_{x}^{y-1} C_{y}^{y} = \sum_{i=0}^{y-1} C_{x}^{i} C_{y}^{i+1}$code

而後算一下,哦喲 $O(n^2)$ 的優秀算法,GG,想了半天也不知道咋優化,看了題解才知道是「範德蒙德恆等式」:blog

$\sum_{i=0}^{r} C_{m}^{i} C_{n}^{r-i} = C_{m+n}^{r}$get

以及它的一個推導等式it

$\sum_{i=0}^{m} C_{m}^{i} C_{n}^{r+i} = C_{m+n}^{m+r}$class

① 直接用推導等式能夠獲得:di

$\sum_{i=0}^{x} C_{x}^{i} C_{y}^{i+1} = C_{x+y}^{x+1}$

而 ② 則用範德蒙德恆等式獲得:

$\sum_{i=0}^{y-1} C_{x}^{i} C_{y}^{i+1} = \sum_{i=0}^{y-1} C_{x}^{i} C_{y}^{y-1-i} = C_{x+y}^{y-1}$

綜上,就變成了:對於每一個 "(",假設其左邊還有 $x$ 個 "(",右邊有 $y$ 個 ")",那麼對於答案的貢獻:

  ① 若 $x+1 \le y$,則爲 $C_{x+y}^{x+1}$

  ② 若 $x+1 > y$,則爲 $C_{x+y}^{y-1}$

只要預處理出階乘和階乘的逆元,那麼每次算 $C_{n}^{r}$ 就是 $O(1)$ 的。

 

AC代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=2e5+10;

char s[maxn];
int n,x[maxn],y[maxn];

ll fpow(ll a,ll n)
{
    ll res=1, base=a%mod;
    while(n)
    {
        if(n&1) res*=base, res%=mod;
        base*=base, base%=mod;
        n>>=1;
    }
    return res%mod;
}
ll inv(ll a){return fpow(a,mod-2);}

ll fac[maxn],fac_inv[maxn];
ll C(ll n,ll r)
{
    ll res=fac[n];
    res*=fac_inv[r], res%=mod;
    res*=fac_inv[n-r], res%=mod;
    return res;
}

int main()
{
    fac[0]=1, fac_inv[0]=inv(fac[0]);
    for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod, fac_inv[i]=inv(fac[i]);

    scanf("%s",s+1), n=strlen(s+1);

    x[1]=0;
    for(int i=2;i<=n;i++) x[i]=x[i-1]+(s[i-1]=='(');
    y[n]=0;
    for(int i=n-1;i>0;i--) y[i]=y[i+1]+(s[i+1]==')');
    //for(int i=1;i<=n;i++) printf("%d %d\n",x[i],y[i]);

    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]!='(') continue;
        if(y[i]<=0) continue;
        if(x[i]+1<=y[i])
            ans+=C(x[i]+y[i],x[i]+1), ans%=mod;
        else
            ans+=C(x[i]+y[i],y[i]-1), ans%=mod;
    }
    cout<<ans<<endl;
}
相關文章
相關標籤/搜索