zoukankan      html  css  js  c++  java
  • Namomo Test Round 1

    题目链接

    https://namomo.top:8081/problem/1005

    tag

    线段树

    solution

    对于看不见的操作,有两种情况:
    ​ 1) 如果兔子在第(i)个帽子下面,操作完后帽子仍在第(i)个帽子下,我们可能选择除第(i)个帽子以外的任意两个帽子进行交换,概率为(frac{C_{n-1}^{2}}{C_{n}^{2}})
    2)如果兔子不在第(i)给帽子下面, 则需要操作后兔子在第(i)个帽子下,此时我们只有一种操作可能,即将兔子所在的帽子和第(i)个帽子交换,概率为 (frac{1}{C_n^2})
    所以有(p[i] = frac{p[i] * C_{n-1}^{2}}{C_{n}^{2}} + frac{(1 - p[i])}{C_n^2})

    对于看得见的操作,直接(swap(p[x], p[y]))

    发现维护p[i]的值需要的进行操作有单点修改,单点查询,区间加法,区间乘法,建一个线段树就可以解决了,另外分数取模需要用到逆元

    时间复杂度为(O(n + k + mlogn))

    code

    //created by pyoxiao on 2020/07/06
    #include<bits/stdc++.h>
    #define LL long long
    #define ll long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define CL(a, b) memset(a, b, sizeof(a))
    using namespace std;
    const LL mod = 998244353, p = mod;
    LL fpow(LL a, LL b, LL p = mod){LL ans = 1; a %= p; while(b) {if(b & 1) ans = ans * a % p; b >>= 1; a = a * a % p;} return ans;}
    LL gcd(LL a, LL b){return b == 0 ? a : gcd(b, a % b);}
    LL inv(LL x) {return fpow(x, mod - 2);}
    const int N = 2e5 + 7;
    LL n, m, k, op[N], x[N], y[N];
    struct seg{
        int l, r;
        LL sum, add, mul;
    }tr[N << 2];
    void push_up(int p) {
        tr[p].sum = (tr[p << 1].sum + tr[p << 1 | 1].sum) % mod;
        tr[p].add = 0; tr[p].mul = 1;
    }
    void build(int l, int r, int p) {
        tr[p].l = l; tr[p].r = r; tr[p].add = 0; tr[p].mul = 1; tr[p].sum = 0;
        if(l == r) {
            return;
        }
        int mid = l + r >> 1;
        build(l, mid, p << 1);
        build(mid + 1, r, p << 1 | 1);
        push_up(p);
    }
    void change(int p, LL add, LL mul) {
        tr[p].mul = tr[p].mul * mul % mod;
        tr[p].add = (tr[p].add * mul % mod + add) % mod;
        tr[p].sum = ((tr[p].sum * mul % mod + add * (tr[p].r - tr[p].l + 1) % mod) % mod + mod) % mod;
    }
    void push_down(int p) {
        change(p << 1, tr[p].add, tr[p].mul);
        change(p << 1 | 1, tr[p].add, tr[p].mul);
        tr[p].add = 0; tr[p].mul = 1;
    }
    void update(int p, int l , int r, LL add, LL mul) {
        if(l <= tr[p].l && tr[p].r <= r) {
            change(p, add, mul);
            return;
        }
        push_down(p);
        int mid = tr[p].l + tr[p].r >> 1;
        if(l <= mid) update(p << 1, l, r, add, mul);
        if(r > mid) update(p << 1 | 1, l, r, add, mul);
        push_up(p);
    }
    void update2(int p, int pos, LL val) {
        if(tr[p].l == pos && tr[p].r == pos) {
            tr[p].sum = val; tr[p].add = 0; tr[p].mul = 1;
            return;
        }
        push_down(p);
        int mid = tr[p].l + tr[p].r >> 1;
        if(pos <= mid) update2(p << 1, pos, val);
        else update2(p << 1 | 1, pos, val);
        push_up(p);
    }
    LL query(int p, int l, int r) {
        if(l <= tr[p].l && tr[p].r <= r) return tr[p].sum;
        push_down(p);
        LL ans = 0;
        int mid = tr[p].l + tr[p].r >> 1;
        if(l <= mid) ans += query(p << 1, l, r), ans %= mod;
        if(r > mid) ans += query(p << 1 | 1, l, r), ans %= mod;
        return ans % mod;
    }
    void solve() {
        scanf("%lld %lld %lld", &n, &m, &k);
        build(1, n, 1);
        update2(1, 1, 1);
        for(int i = 1; i <= m; i ++) op[i] = 0;
        for(int i = 1; i <= k; i ++) {
            int a, b, c;
            scanf("%d %d %d", &a, &b, &c);
            op[a] = 1; x[a] = b; y[a] = c;
        }
        int pos = 1;
        LL add = (2LL *  inv(n * (n - 1)) % mod + mod) % mod, mul = (((n - 2) * inv(n) % mod - 2LL * inv(n * (n - 1)) % mod + mod) % mod + mod) % mod;
        for(int i = 1; i <= m; i ++) {
            if(op[i]) {
                LL tmp1 = query(1, x[i], x[i]), tmp2 = query(1, y[i], y[i]);
                update2(1, x[i], tmp2);
                update2(1, y[i], tmp1);
            } else {
                update(1, 1, n, add, mul);
            }
        }
        for(int i = 1; i <= n; i ++) printf("%lld%c", (query(1, i, i) % mod + mod) % mod, i == n ? '
    ' : ' ');
    }
    int main() {
        int T = 1;
        scanf("%d", &T);
        while(T --) 
            solve();
        return 0;
    }
    
  • 相关阅读:
    day84:luffy:优惠活动策略&用户认证&购物车商品的勾选/结算
    day83:luffy:添加购物车&导航栏购物车数字显示&购物车页面展示
    day82:luffy:课程详情页面显示&章节和课时显示&视频播放组件&CKEditor富文本编辑器
    day81:luffy:课程分类页面&课程信息页面&指定分类显示课程信息&分页显示课程信息
    day80:luffy:短信sdk接入&点击获取验证码&注册功能的实现&Celery实现短信发送功能
    day79:luffy:注册之对手机号的验证&实现基本的注册功能逻辑&点击获取验证码&redis
    day78:luffy:前端对于token的认证&滑动验证码的实现
    day77:luffy:导航栏的实现&DjangoRestFramework JWT&多条件登录
    day76:luffy:项目前端环境搭建&轮播图的实现
    day75:luffy:路飞学城项目后端环境搭建&Git相关知识点
  • 原文地址:https://www.cnblogs.com/pyoxiao/p/13255346.html
Copyright © 2011-2022 走看看