首页 > 其他分享 >2024牛客多校 4 (概率,带权并查集,构造)

2024牛客多校 4 (概率,带权并查集,构造)

时间:2024-09-20 17:17:19浏览次数:1  
标签:frac int ll 查集 多校 long 2024 dp mod

2024牛客多校 4 (概率,带权并查集,构造)

J - Zero

题面:给出整数 \(n\) 和 \(k\) , 一个 0 1 ? 字符串 \(s\) 。

? 有概率是 0 或是 1,且概率相等,一段区间 \([l, r]\) 的贡献这样计算:

  • 这一段区间不包含 0

  • 贡献为长度的 \(k\) 次方

求这个字符串 \(s\) 的期望贡献是多少?

solution:

首先应该考虑如何统计贡献,如果遍历区间,到达了复杂度 \(O(n^2)\) 复杂度。

于是自然想到统计每一位的贡献,开始想到统计第 \(i\) 位出现的所有区间的贡献,但尝试过之后发现难以实现,重点来了,计算第 \(i\) 位结尾所得的贡献。

\(dp[i]\) 表示第 \(i\) 位结尾所得的贡献 ,于是列式计算:

若子串为 ????

则 \(f[3]\) 表示为 \({\frac{1}{2}}^1 * 1^k + {\frac{1}{2}}^2 * 2^k + {\frac{1}{2}}^3 * 3^k\)

$f[4] = $ \({\frac{1}{2}}^1 * 1^k + {\frac{1}{2}}^2 * 2^k + {\frac{1}{2}}^3 * 3^k + {\frac{1}{2}}^4 * 4^k\)

自然想到如何从 \(f[3]\) 变化到 \(f[4]\) ,这个时候联想一下数组推移的样子,首先多了一项长度为 1 的,其次前面每一项都长度加 1 ,用 \(f[4]\) 减去 \(f[3]\) 可得一个简单的式子:

\[(x + 1)^k - x^k = \sum_{i = 0}^{k - 1} C_{k}^{i} * x^i \]

所以发现需要计算 \(k\) 次方的答案需要用到 0 - (k - 1) 的结果,于是升级定义

定义 \(dp[i][j]\) 表示第 \(i\) 位结尾,\(k = j\) 时的贡献

细节为底层特殊情况应该需要特殊判断去赋值,然后递推公式就是:

\[dp[i][j]=\left\{\begin{aligned}dp[i-1][j] + 1 + \sum_{i = 0}^{k - 1} C_{k}^{i} * dp[i - 1][i], s[i] = 1\\ \frac 12 *(dp[i-1][j] + 1 + \sum_{i = 0}^{k - 1} C_{k}^{i} * dp[i - 1][i]), s[i] = ?\\\end{aligned}\right. \]

参考代码如下:

// Created by qyy on 2024/9/13.

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define PII pair<int, int>
#define endl "\n"

const long long inf = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 10;
const long long mod = 998244353;

int n, k;
ll dp[N][32];
string s;

ll fast_pow(ll a, ll n){
    ll ans = a % mod;
    while(n){
        if(n & 1){
            ans = (ans * a) % mod;
        }
        a = (a * a) % mod;
        n >>= 1;
    }
    return ans;
}
ll inv(ll x){
    return fast_pow(x, mod - 2);
}

ll C[50][50];


ll cal(int beg, int ed){
    if(beg > ed){
        return 0;
    }
    int len = ed - beg + 1;
    for(int i = 0; i <= len; i++){
        for(int j = 0; j <= 30; j++){
            dp[i][j] = 0;
        }
        if(i != 0){
            dp[i][0] = 1;
        }
    }

    ll ans = 0;
    if(s[beg] == '?'){
        dp[1][0] = inv(2);
    }else{
        dp[1][0] = 1;
    }
    for(int j = 1; j <= k; j++){
        dp[1][j] = dp[1][j - 1];
    }
    for(int j = 0; j <= k; j++){
        for(int i = 2; i <= len; i++){
            int pos = beg + i - 1;
            ll res = 1;
            for(int x = 0; x < j; x++){
                ll tmp = C[j][x] * dp[i - 1][x];
                res = (res + tmp) % mod;
            }
            res = (res + dp[i - 1][j]) % mod;
            if(s[pos] == '?'){
                dp[i][j] = (res * inv(2)) % mod;
            }else{
                dp[i][j] = res;
            }
        }
    }
    for(int i = 1; i <= len; i++){
        ans = (ans + dp[i][k]) % mod;
    }
    return ans;
}

void solve() {
    cin >> n >> k;
    cin >> s;

    for(int i = 1; i <= 40; i++){
        C[i][0] = C[i][i] = 1;
        for(int j = 1; j < i; j++){
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
        }
    }
    s.push_back('0');
    int len = s.size();
    int beg = 0, ed = 0;
    ll ans = 0;
    for(int i = 0; i < len; i++){
        if(s[i] == '0'){
            ed = i - 1;
            ans = (ans + cal(beg, ed)) % mod;
            beg = i + 1;
        }
    }
    cout << ans % mod << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

标签:frac,int,ll,查集,多校,long,2024,dp,mod
From: https://www.cnblogs.com/9102qyy/p/18422871

相关文章

  • 2024.8.30校测
    T1题目描述物理老师YJ有一个长杆天平,天平的两臂长均为\(15\),将长杆看作\(x\)轴,则平衡点在\(0\)位置处,负数位置在左臂上,正数位置在右臂上。长杆上有\(n\)个位置有挂钩可以挂秤砣。YJ有\(m\)个秤砣,质量分别为\(g_i\),每个挂钩可以不挂也可以挂任意个秤砣。YJ想要知道......
  • 分块/莫队学习笔记(一)(2024.8.23)
    分块基本概念分块的基本思想是,通过对原数据的适当划分,并在划分后的每一个块上预处理部分信息,从而较一般的暴力算法取得更优的时间复杂度。分块的时间复杂度主要取决于分块的块长,一般可以通过均值不等式求出某个问题下的最优块长,以及相应的时间复杂度。LOJ小分块#6277.数列分......
  • 2024.8.31校测
    T1题目描述今天的酒席有\(n\)个人,他们要同时举杯,成对碰杯。碰杯的时候,不能有人不参与碰杯,也不希望有手臂交叉这种别扭的情况出现。如下图,左图的情况是好的,右图的情况是不希望出现的。每个人都有一个喜爱的酒种类,每个人想要与和自己喝一样酒的人碰杯,请你设计一个方法,在保证每......
  • 2024.9.6校测
    T1题目描述猫猫是丛林里很多动物心中的天使,她为此十分自豪。猫猫最爱吃鱼了,她每天都要去池塘钓鱼吃。猫猫经常吃鱼脑,数学特别强,然而,小女生的性格决定了她的贪玩。一天,猫猫钓到了很多条鱼。她并不想马上就把可怜的鱼儿吃掉,而是先折磨够之后再吃(有句话叫什么来着,最毒不过猫猫心)。......
  • 2024.9.16上午校测
    T1题目描述首先,让我们来一道萌萌哒的并查集吧。你有\(n\)个萌萌哒元素。每个元素都单独在一个集合中。同时,我们有\(n-1\)个操作,每次合并两个元素所在的集合,保证合并前两个元素位于不同的集合。现在有\(m\)个询问\((x,y)\),每次询问需要你输出元素\(x,y\)第一次位......
  • 2024.9.13校测
    T1题目描述Gnaw刚刚学习在数字逻辑中学到了格雷码,它的定义是这样的,对于二进制数\(A\),它对应的格雷码为\(G=A\operatorname{xor}(A>>1)\),格雷码有个很有趣的性质是相邻二进制数对应的格雷码只有一位不同。现在以\(01?\)的方式给出一个长为的二进制数\(m\),\(?\)表示......
  • 2024.9.16下午校测
    T1题目描述有\(n\)个人站成一行,每个人有一个魅力值,相同魅力值的人会形成一个团伙,你出于对于社会和谐发展的考虑,定义一个团伙正常当且仅当团伙人数为\(2\),现在你的任务就是回答\(M\)个询问,每次询问一个区间\([L,R]\),你需要回答这个区间中所有人各自结成团伙后,处于不正常团......
  • 2024-09-20 如何去除vue前端框架upload组件中的缓存 ==》v-if+setTimeout
    在很多前端框架中的upload组件,比如arco-design的a-upload组件,在遍历渲染过程中会发现上传完成后,切换到另一个a-upload组件,它的图片会显示上一个a-upload组件的缓存 正常上传,然后点击红色,红色对应的图片应该被清空,实际上却并没有,如下解决方案:给a-upload组件加一个条件判断v-if......
  • 图论进阶学习笔记(三)(2024.8.12)
    二分图定义如果你能把一个图划分成两个集合,集合内部的点没有边相连接,那么这个图就是一个二分图,如图就是一个二分图:交错路:从一个没有被匹配的点出发,依次走非匹配边,匹配边,非匹配边……最后到达另外一部点当中某个没有被匹配的点的路径。增广路:从一个没有被匹配的点出发,依次走......
  • 图论进阶学习笔记(二)(2024.8.1)
    图的连通性强连通分量割点缩点例题一边双连通分量点双连通分量2-SAT例题二例题三欧拉回路例题四......