花火之声不闻于耳 [线段树]

花火之声不闻于耳




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;
}
原文地址:https://www.cnblogs.com/zbr162/p/11822483.html