zoukankan      html  css  js  c++  java
  • 花火之声不闻于耳 [线段树]

    花火之声不闻于耳




    color{red}{正解部分}

    现在要求的是 φ(i=LRai)=i=LRai×pj1pjvarphi left( prod_{i=L}^R a_i ight) = prod_{i=L}^R a_i imes prod frac{p_j-1}{p_j},

    答案只与 aia_i 的值 和 其包含的质数有关, 而题目中涉及到的质数不超过 6262 个 .

    于是使用两颗线段树, 一颗记录乘积的信息, 一颗记录相关质数出现的信息,
    其中质数出现的信息可以以二进制形式存储到 long longlong long 中 .


    color{red}{实现部分}

    • 注意线段树乘法懒标记初值为 11 .
    • <<<< 不要写成 << .
    • 1<<x1<<x 应该为 1ll<<x1ll<<x.
    #include<bits/stdc++.h>
    #define reg register
    typedef long long ll;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1e6 + 5;
    const int mod = 998244353;
    
    int N;
    int M;
    int p_cnt;
    int A[maxn];
    int pos[maxn];
    int from[maxn];
    int prime[maxn];
    int p_inv[maxn];
    
    bool vis[maxn];
    
    ll State;
    
    int Ksm(int a, int b){ int s=1; while(b){ if(b&1) s=1ll*s*a%mod; a=1ll*a*a%mod; b>>=1; } return s; }
    
    void sieve(){
            for(reg int i = 2; i <= 300; i ++){
                    if(!vis[i]) prime[++ p_cnt] = i, p_inv[p_cnt] = (1ll*i-1)*Ksm(i, mod-2)%mod, from[i] = i, pos[i] = p_cnt;
                    for(reg int j = 1; j <= p_cnt && prime[j]*i <= 300; j ++){ 
                            vis[prime[j]*i] = 1; from[prime[j]*i] = prime[j]; 
                            if(i % prime[j] == 0) break ;
                    }
            }
    }
    
    ll Calc_zt(int x){ ll res=0; while(x > 1){ res |= (1ll<<pos[from[x]]-1); x /= from[x]; } return res; }
    
    struct Segment_Tree{
    
            struct Node{ int l, r, sum, tag_1; ll zt, tag_2; } T[maxn << 2];
    
            void Build(int k, int l, int r){
                    T[k].l = l, T[k].r = r, T[k].tag_1 = 1, T[k].tag_2 = 0;
                    if(l == r){ T[k].sum = A[l]; T[k].zt = Calc_zt(A[l]); return ; }
                    int mid = l+r >> 1;
                    Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
                    T[k].sum = 1ll*T[k<<1].sum * T[k<<1|1].sum % mod;
                    T[k].zt = T[k<<1].zt | T[k<<1|1].zt;
            }
    
            void Push_down(int k){
                    int lt = k<<1, rt = k<<1|1, len = T[k].r-T[k].l+1;
                    T[k].sum = 1ll*T[k].sum*Ksm(T[k].tag_1, len)%mod, T[k].zt |= T[k].tag_2; 
                    T[lt].tag_1 = 1ll*T[lt].tag_1*T[k].tag_1 % mod;
                    T[rt].tag_1 = 1ll*T[rt].tag_1*T[k].tag_1 % mod;
                    T[lt].zt |= T[k].tag_2, T[lt].tag_2 |= T[k].tag_2;
                    T[rt].zt |= T[k].tag_2, T[rt].tag_2 |= T[k].tag_2;
                    T[k].tag_1 = 1, T[k].tag_2 = 0;
            }
    
            void Modify(int k, const int &ql, const int &qr, const int &x, const ll &st){
                    if(T[k].tag_1 != 1 || T[k].tag_2) Push_down(k);
                    int l = T[k].l, r = T[k].r;
                    if(ql > r || qr < l) return ;
                    if(ql <= l && r <= qr){
                            T[k].tag_1 = 1ll*T[k].tag_1*x % mod;
                            T[k].tag_2 |= st, T[k].zt |= st;
                            Push_down(k);
                            return ;
                    }
                    int mid = l+r >> 1;
                    Modify(k<<1, ql, qr, x, st);
                    Modify(k<<1|1, ql, qr, x, st);
                    T[k].sum = 1ll*T[k<<1].sum*T[k<<1|1].sum % mod;
                    T[k].zt = T[k<<1].zt | T[k<<1|1].zt;
            }
    
            int Query(int k, const int &ql, const int &qr){
                    if(T[k].tag_1 != 1 || T[k].tag_2) Push_down(k);
                    int l = T[k].l, r = T[k].r;
                    if(ql > r || qr < l) return 1;
                    if(ql <= l && r <= qr){ State |= T[k].zt; return T[k].sum; }
                    int mid = l+r >> 1, res = 1;
                    res = 1ll*res*Query(k<<1, ql, qr) % mod;
                    res = 1ll*res*Query(k<<1|1, ql, qr) % mod;
                    return res;
            }
    
    } seg_t;
    
    int main(){
            freopen("hanabi.in", "r", stdin);
            freopen("hanabi.out", "w", stdout);
            sieve(); N = read(), M = read();
            for(reg int i = 1; i <= N; i ++) A[i] = read(); 
    
            seg_t.Build(1, 1, N);
    
    
    /*
            int res = 0;
            res = seg_t.Query(1, 233, 90000);
            std::cout << res << std::endl;
            for(reg int j = 1; j <= p_cnt; j ++) if(State & (1ll<<j-1)) res = 1ll*res*p_inv[j]%mod;
            std::cout << State << std::endl;
    
    */
    
            for(reg int i = 1; i <= M; i ++){
                    int op = read(), L = read(), R = read();
                    if(op == 1){ int x = read();
                            seg_t.Modify(1, L, R, x, Calc_zt(x)); 
    
                    } else{
                            State = 0;
                            int res = seg_t.Query(1, L, R);
                            for(reg int j = 1; j <= p_cnt; j ++) if(State & (1ll<<j-1)) res = 1ll*res*p_inv[j]%mod;
                            printf("%d
    ", res);
                    }
            }
            return 0;
    }
    
  • 相关阅读:
    Redis数据库
    Nginx介绍
    shell脚本基础
    iptables防火墙
    Web自动化测试—Selenium文件操作
    Web自动化测试——Selenium之发送163邮件
    Web自动化测试—Selenium webdriver的基本操作
    Web自动化测试—webdriver的环境配置
    Web自动化测试—Selenium IDE的安装与使用
    Web自动化测试—什么是Selenium?
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822483.html
Copyright © 2011-2022 走看看