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

本文介绍了一种使用线段树和质数优化解决特定数学问题的方法。通过两颗线段树,一颗用于记录乘积信息,另一颗用于记录质数出现的信息,解决了与质数相关的大规模计算问题。文章详细介绍了算法实现过程,包括初始化、查询和修改操作。

花 火 之 声 不 闻 于 耳 花火之声不闻于耳




正 解 部 分 \color{red}{正解部分}

现在要求的是 φ ( ∏ i = L R a i ) = ∏ i = L R a i × ∏ p j − 1 p j \varphi \left( \prod_{i=L}^R a_i \right) = \prod_{i=L}^R a_i \times \prod \frac{p_j-1}{p_j} φ(i=LRai)=i=LRai×pjpj1,

答案只与 a i a_i ai 的值 和 其包含的质数有关, 而题目中涉及到的质数不超过 62 62 62 个 .

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


实 现 部 分 \color{red}{实现部分}

  • 注意线段树乘法懒标记初值为 1 1 1 .
  • < < << << 不要写成 < < < .
  • 1 < < x 1<<x 1<<x 应该为 1 l l < < x 1ll<<x 1ll<<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\n", res);
                }
        }
        return 0;
}
【完美复现】面向配电网韧性提升的移动储能预布局与动态调度策略【IEEE33节点】(Matlab代码实现)内容概要:本文介绍了基于IEEE33节点的配电网韧性提升方法,重点研究了移动储能系统的预布局与动态调度策略。通过Matlab代码实现,提出了一种结合预配置和动态调度的两阶段优化模型,旨在应对电网故障或极端事件时快速恢复供电能力。文中采用了多种智能优化算法(如PSO、MPSO、TACPSO、SOA、GA等)进行对比分析,验证所提策略的有效性和优越性。研究仅关注移动储能单元的初始部署位置,还深入探讨其在故障发生后的动态路径规划与电力支援过程,从而全面提升配电网的韧性水平。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事智能电网、能源系统优化等相关领域的工程技术人员。; 使用场景及目标:①用于科研复现,特别是IEEE顶刊或SCI一区论文中关于配电网韧性、应急电源调度的研究;②支撑电力系统在灾害或故障条件下的恢复力优化设计,提升实际电网应对突发事件的能力;③为移动储能系统在智能配电网中的应用提供理论依据和技术支持。; 阅读建议:建议读者结合提供的Matlab代码逐模块分析,重点关注目标函数建模、约束条件设置以及智能算法的实现细节。同时推荐参考文中提及的MPS预配置与动态调度上下两部分,系统掌握完整的技术路线,并可通过替换同算法或测试系统进一步拓展研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值