• Codeforces 1109E Sasha and a Very Easy Test 线段树


    因为mod不是质数, 所以要处理一下除的操作, 考虑吧mod分解质因数, 然后把所有数都按mod

    分解出来的质因数进行拆分, 然后就能维护了。

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    const int N = (int)1e5 + 7;
    
    int mod;
    
    struct Bit {
        int a[N];
        inline void modify(int x, int v) {
            for(int i = x; i < N; i += i & -i) {
                a[i] += v;
            }
        }
        int sum(int x) {
            int ans = 0;
            for(int i = x; i; i -= i & -i) {
                ans += a[i];
            }
            return ans;
        }
    };
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    struct SegmentTree {
        int sum[N << 2];
        int lazy[N << 2];
        inline void pull(int rt) {
            sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
            if(sum[rt] >= mod) sum[rt] -= mod;
        }
        inline void push(int rt) {
            if(lazy[rt] != 1) {
                sum[rt << 1] = 1LL * sum[rt << 1] * lazy[rt] % mod;
                sum[rt << 1 | 1] = 1LL * sum[rt << 1 | 1] * lazy[rt] % mod;
                lazy[rt << 1] = 1LL * lazy[rt << 1] * lazy[rt] % mod;
                lazy[rt << 1 | 1] = 1LL * lazy[rt << 1 | 1] * lazy[rt] % mod;
                lazy[rt] = 1;
            }
        }
        void build(int l, int r, int rt) {
            lazy[rt] = 1;
            if(l == r) {
                sum[rt] = 1;
                return;
            }
            int mid = l + r >> 1;
            build(lson); build(rson);
            pull(rt);
        }
        void update(int L, int R, int val, int l, int r, int rt) {
            if(R < l || r < L || R < L) return;
            if(L <= l && r <= R) {
                sum[rt] = 1LL * sum[rt] * val % mod;
                lazy[rt] = 1LL * lazy[rt] * val % mod;
                return;
            }
            push(rt);
            int mid = l + r >> 1;
            update(L, R, val, lson);
            update(L, R, val, rson);
            pull(rt);
        }
        void update2(int p, int val, int l, int r, int rt) {
            if(l == r) {
                sum[rt] = val;
                return;
            }
            push(rt);
            int mid = l + r >> 1;
            if(p <= mid) update2(p, val, lson);
            else update2(p, val, rson);
            pull(rt);
        }
        int query(int L, int R, int l, int r, int rt) {
            if(R < l || r < L || R < L) return 0;
            if(L <= l && r <= R) return sum[rt];
            push(rt);
            int mid = l + r >> 1;
            return (query(L, R, lson) + query(L, R, rson)) % mod;
        }
    };
    
    int n, q, a[N];
    SegmentTree real_val, inv_val;
    Bit bit[10];
    int mul_val[N];
    vector<int> F, C;
    vector<int> V[N];
    
    int power(int a, int b) {
        int ans = 1;
        while(b) {
            if(b & 1) ans = 1LL * ans * a % mod;
            a = 1LL * a * a % mod; b >>= 1;
        }
        return ans;
    }
    
    void mul_modify(int L, int R, int val) {
        if(val == 1) return;
        inv_val.update(L, R, mul_val[val], 1, n, 1);
        real_val.update(L, R, val, 1, n, 1);
        for(int i = 0; i < V[val].size(); i++) {
            if(!V[val][i]) continue;
            bit[i].modify(L, V[val][i]);
            bit[i].modify(R + 1, -V[val][i]);
        }
    }
    
    int ex_gcd(int a, int b, int &x, int &y) {
        if(b == 0) {
            x = 1; y = 0;
            return a;
        }
        int r = ex_gcd(b, a % b, x, y);
        int t = x;
        x = y; y = t - a / b * y;
        return r;
    }
    
    int inv(int a, int mod) {
        int d, x, y;
        d = ex_gcd(a, mod, x, y);
        if(d == 1) return (x % mod + mod) % mod;
        else assert(0);
    }
    
    void div_modify(int p, int val) {
        if(val == 1) return;
        for(int i = 0; i < V[val].size(); i++) {
            if(!V[val][i]) continue;
            bit[i].modify(p, -V[val][i]);
            bit[i].modify(p + 1, V[val][i]);
        }
        int gg = 1;
        for(int i = 0; i < F.size(); i++) {
            gg = 1LL * gg * power(F[i], bit[i].sum(p)) % mod;
        }
        int nex_inv = 1LL * inv_val.query(p, p, 1, n, 1) * inv(mul_val[val], mod) % mod;
        inv_val.update2(p, nex_inv, 1, n, 1);
        if(gg) real_val.update2(p, 1LL * nex_inv * gg % mod, 1, n, 1);
    }
    
    int query(int L, int R) {
        return real_val.query(L, R, 1, n, 1);
    }
    
    void show() {
        puts("");
        for(int i = 1; i <= n; i++) {
            printf("%d ", real_val.query(i, i, 1, n, 1));
        }
        puts("");
    }
    
    int main() {
        scanf("%d%d", &n, &mod);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        real_val.build(1, n, 1);
        inv_val.build(1, n, 1);
        int tmp = mod;
        for(int i = 2; i * i <= tmp; i++) {
            if(tmp % i) continue;
            F.push_back(i);
            int cnt = 0;
            while(tmp % i == 0) {
                cnt++;
                tmp /= i;
            }
            C.push_back(cnt);
        }
        if(tmp > 1) F.push_back(tmp), C.push_back(1);
        for(int i = 2; i <= 100000; i++) {
            mul_val[i] = i;
            for(auto &t : F) {
                while(mul_val[i] % t == 0) {
                    mul_val[i] /= t;
                }
            }
        }
        for(int i = 2; i <= 100000; i++) {
            for(int j = 0; j < F.size(); j++) {
                int cnt = 0, now = i;
                while(now % F[j] == 0) {
                    cnt++;
                    now /= F[j];
                }
                V[i].push_back(cnt);
            }
        }
        for(int i = 1; i <= n; i++) {
            mul_modify(i, i, a[i]);
        }
        scanf("%d", &q);
        while(q--) {
            int op; scanf("%d", &op);
            if(op == 1) {
                int l, r, x;
                scanf("%d%d%d", &l, &r, &x);
                mul_modify(l, r, x);
            }
            else if(op == 2) {
                int p, x;
                scanf("%d%d", &p, &x);
                div_modify(p, x);
            }
            else {
                int l, r;
                scanf("%d%d", &l, &r);
                printf("%d
    ", query(l, r));
            }
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    IntelliJ IDEA AndroidStudio SVN无法使用
    三极管封装
    STC等单片机一开机就停电模式烧写程序办法
    CC2541设置中断输入模式
    C# WinForm 多线程 应用程序退出的方法 结束子线程
    CorelDrawX8安装时提示已安装另一个版本
    Win10下Prolific USB-to-Serial Comm Port驱动提示不能使用
    Keil5创建GPIO
    SQL行列转置
    Excel复制粘贴假死
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11681600.html
Copyright © 2020-2023  润新知