洛谷 P11487 「Cfz Round 5」Gnirts 10——题解

洛谷P11487「Cfz Round 5」Gnirts 10


传送锚点


摸鱼环节

「Cfz Round 5」Gnirts 10

题目背景

English statement. You must submit your code at the Chinese version of the statement.


In Memory of \(\text{F}\rule{66.8px}{6.8px}\).

题目描述

题面还是简单一点好。

  • 给定 \(n, m\),以及一个长为 \(n + m\)\(\tt{01}\)\(S\)
  • 对于 \(\tt 01\)\(T\),定义 \(f(T)\)\(S\) 的最长的前缀的长度,使得该前缀是 \(T\) 的子序列 \(^\dagger\)
  • 对于每个 恰包含 \(\bm n\)\(\tt 1\)\(\bm m\)\(\tt 0\) \(\tt{01}\)\(T\),求 \(f(T)\) 的和。答案对 \(2933256077^\ddagger\) 取模。

\(\dagger\):请注意,子序列可以不连续。换句话说,\(a\)\(b\) 的子序列,当且仅当在 \(b\) 中删去 \(\geq 0\) 个字符后,可以得到 \(a\)。注意,空串总是任何串的子序列。

\(\ddagger\):模数为质数。

输入格式

第一行包含两个整数 \(n, m\)

第二行包含一个长度为 \(n + m\)\(\tt 01\)\(S\)

输出格式

输出一行一个整数,表示答案对 \(2933256077\) 取模后的结果。

样例 #1

样例输入 #1

2 1
000

样例输出 #1

3

样例 #2

样例输入 #2

5 5
0010111011

样例输出 #2

1391

提示

「样例解释 #1」

所有可能的序列有且仅有公共序列 \(\texttt{0}\)。因为恰有 \(3\) 种不同的 \(T\)\(\tt 110, 101, 011\)),所以答案为 \(1\times 3 = 3\)

「数据范围」

对于所有测试数据,保证 \(1 \leq n, m \leq 3\times 10^6\)

本题采用捆绑测试。

  • Subtask 0(13 points):\(\max(n, m) \leq 5\)
  • Subtask 1(13 points):\(\max(n, m) \leq 100\)
  • Subtask 2(34 points):\(\max(n, m) \leq 3 \times 10^3\)
  • Subtask 3(40 points):无特殊限制。

大数学。


正片开始

考虑到我们只关心答案,而答案只需要 \(S\) 某种前缀的个数,并不需要考虑具体的方案,于是我们可以从前缀的方向考虑。

对于答案而言,首先答案对质数取模,其次每个合法的\(T\),可以看作是 \(n\)\(1\)\(m\)\(0\) 的一种组合。于是得到暴力枚举每种组合计算答案的朴素算法,很显然,这只能搞到13分。

考虑对 \(S\) 的前缀一位位处理答案,对于一个 \(S\) 的前缀 \(k\) ,长度为 \(l\) ,其中有 \(cnt0\)\(0\)\(cnt1\)\(1\)

假设第 \(l+1\) 位为 \(1\) ,那显然,剩下的 \(n-cnt1\)\(1\) 只能插在第 \(l\) 位之前,不然会导致前缀变长。
也就是要把 \(n-cnt1\)\(1\) 分散在 \(cnt0\)\(0\) 之间,两个 \(0\) 之间可以没有1。
于是插入\(1\)的答案为 \(\dbinom{n-cnt1+cnt0-1}{cnt0-1}\) 同理, \(0\) 则是有 \(cnt1\) 块板,于是 \(0\) 的答案 \(\dbinom{m-cnt0+cnt1}{cnt1}\)

一位的答案为:

\[ g(l)=\begin{cases} \dbinom{n-cnt1+cnt0-1}{cnt0-1}\times \dbinom{m-cnt0+cnt1}{cnt1},S_{l+1}=1\\ \dbinom{n-cnt0+cnt1-1}{cnt1-1}\times \dbinom{m-cnt1+cnt0}{cnt0},S_{l+1}=0\\ \end{cases} \]

$ans=\sum_{i=1}^{n+m} i\times g(i) $。


完整代码

#ifdef ONLINE_JUDGE
#else
#define Qiu_Cheng
#endif
#include <bits/stdc++.h>
#define int long long 
using namespace std;
// typedef long long ll;
const int N=6e6+50,M=1e6,mod=2933256077;
int fac[N],ifac[N],inv[N];
int C(int a,int b)
{
    if(a==b) return 1;
    if(a<b||b<0) return 0;
    return fac[a]*ifac[a-b]%mod*ifac[b]%mod;
}
void YCL()
{

    fac[0]=1;inv[1]=1;ifac[0]=1;
    for(int i=1;i<=6e6;i++)
    {
        fac[i]=fac[i-1]*i%mod;
        if(i>=2)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        ifac[i]=ifac[i-1]*inv[i]%mod;
    }
}
int n,m,len,ans=0;
string s;
inline void solve()
{   
    YCL();
    cin>>n>>m;len=n+m;
    cin>>s;s=' '+s;
    int cnt0=0,cnt1=0;
    for(int i=1;i<=len;i++)
    {
        if(s[i]=='0')cnt0++;
        else cnt1++;
        ans=(ans+i*(s[i+1]=='0'?C(m-cnt0+cnt1-1,cnt1-1)*C(n-cnt1+cnt0,cnt0)%mod:C(n-cnt1+cnt0-1,cnt0-1)*C(m-cnt0+cnt1,cnt1)%mod))%mod;
    }
    cout<<ans<<endl;

}
signed main()
{
#ifdef Qiu_Cheng
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif
    // ios::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    // int QwQ;
    // cin>>QwQ;
    // while(QwQ--)solve();
    solve();
    return 0;
}

//  6666   66666    666666
// 6    6  6    6       6
// 6    6  6666       6
// 6    6  6   6    6
//  6666   6    6  6666666

//g++ -O2 -std=c++14 -Wall "-Wl,--stack= 536870912 " cao.cpp -o cao.exe


完结收工!!!!!

个人主页

看完点赞,养成习惯

\(\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\)

posted @ 2025-01-01 16:21  Nightmares_oi  阅读(7)  评论(0编辑  收藏  举报