主席树 ---- CF 1422F. Boring Queries(由离线推出在线如何求的 ,求解多次询问的区间LCM)

news/2024/7/5 2:27:48

题目链接


题目大意:

给你nnn个数,
每次往第iii个数里面里面乘aaa,问你这nnn个数的LCM\text{LCM}LCM是多少?


解题思路:

多个数的lcm不是所有数的乘积除以所有数的gcd,如 4 8 3
正确求法是每个数分解质因数后求区间每个质因子的最大幂次
做法:由于每个数的范围在2e52e52e5内,不可能存下所有质因子
但是!

  1. 对于大于2e5\sqrt{2e5}2e5的质因子,对于每一个数而言要么数量为000,要么为111
  2. 对于小于2e5\sqrt{2e5}2e5的质数,只有87个

解法1:主席树 + RMQ(卡空间)

  1. 对于上面小于2e5\sqrt{2e5}2e5的质数我们对每个质数都开个rmqrmqrmq:里面是每个位置的幂次最大值
  2. 对于大于2e5\sqrt{2e5}2e5的质因子,我们开个主席树里面的叶子节点是位置,对于每个root[R]root[R]root[R],然后对于同一个质数,我们维护它出现的最右边的位置因为你固定了RRR之后,对于同一个质因子贡献只能算一次,那么我们肯定是要最靠右边的位置,你要查询[L,R][L,R][L,R]的时候直接跑以root[R]root[R]root[R]为根的子树,然后在里面区间查询[L,R][L,R][L,R]就好了
  3. 然后结果就是两部分相乘

解法2: 主席树

  1. 首先我们知道上面有个技巧就是把在固定了RRR之后我们把贡献算到了最后一次出现的位置
  2. 那么我们看看对于RMQRMQRMQ的部分能不能套进行求解?
  3. 我们知道在固定了RRR之后,对于同一个质因子的如果指数大的出现在右边,那么指数比它小并且在它左边的贡献就不算了。就是可以覆盖掉
  4. 但是如果有指数比它小的并且出现在在它的右边?那该怎么办?
  5. 那么我们就可以把一部分的贡献拖过去
  6. 如下图假如我们这里有个5次方的因子(5个方格)后面要3次方的因子
    在这里插入图片描述
    在这里插入图片描述
    贡献转移
    具体实现细节见代码:

ACcode

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 7;
const int maxn = 200010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<int,int> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();int f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}
int n, m, tot;
int Right[maxn];
struct Segtree {int lson, rson;int lcm;
}sgt[maxn * 200];
int root[maxn];
inline void insert(int &now, int last, int l, int r, int pos, int val) {now = ++ tot;sgt[now] = sgt[last];sgt[now].lcm = (1ll * sgt[now].lcm * val) % mod;if(l == r) return;if(pos <= mid) insert(sgt[now].lson,sgt[last].lson,l,mid,pos,val);else insert(sgt[now].rson,sgt[last].rson,mid+1,r,pos,val);
}inline int ask(int now, int l, int r, int ql, int qr) {if(!now) return 1;if(ql <= l && qr >= r) return sgt[now].lcm;int res = 1;if(ql <= mid) res = (1ll * res * ask(sgt[now].lson,l,mid,ql,qr)) % mod;if(qr > mid) res = (1ll * res * ask(sgt[now].rson,mid+1,r,ql,qr)) % mod;return res;
}int inv[maxn];
inline void init() {inv[1]=1;sgt[0].lcm=1; for(int i = 2; i < 2e5 + 10; ++ i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
}int main() {init();read(n);for(int i = 1; i <= n; ++ i) {int x;cin >> x;root[i] = root[i-1];for(int j = 2; 1ll * j * j <= x; ++ j) {int px = 1;while(x % j == 0) {x /= j;px *= j;if(Right[px]) // 每个值上次出现的最右边的位置insert(root[i],root[i],1,n,Right[px],inv[j]);	// 防止被重复除,每次只除一个j	Right[px] = i;}if(px != 1)insert(root[i],root[i],1,n,Right[px],px);}if(x > 1) {if(Right[x]) insert(root[i],root[i],1,n,Right[x],inv[x]);insert(root[i],root[i],1,n,i,x);Right[x] = i;}}read(m);int last = 0;for(int i = 1; i <= m; ++ i) {int u, v;read(u,v);int l, r;l = (last + u) % n + 1;r = (last + v) % n + 1;if(l > r) swap(l,r);cout << (last = ask(root[r],1,n,l,r) % mod) << endl;}return 0;
}

http://lihuaxi.xjx100.cn/news/286082.html

相关文章

春节停车难?用Python找空车位

作者 | Adam Geitgey译者 | 风车云马整理 | Jane出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;【导语】今天这篇文章的选题非常贴近生活。营长生活在北京&#xff0c;深知开车出门最怕的就是堵车和找不到停车位。记得冬至那个周末&#xff0c;几个小伙伴滑雪回来找…

汉字风格迁移篇--中文字体的多任务对抗学习

文章目录 摘要存在的问题提出一种方法INTRODUCTION汉字生成背景RELATED WORK现有的一些方法基于CG的方法存在的问题METHOD DESCRIPTIONA、Problem F ormulationB、Base ModelC、MTfontGAN Network AchitecturesD、Objective FunctionE. Training ProcessEXPERIMENTSA、Experime…

poj2594(最小可相交覆盖路径问题)

最小可相交覆盖&#xff1a; 先用floyd求出原图的传递闭包&#xff0c;即如果a->b有路径&#xff0c;b->c有路径&#xff0c;&#xff0c;则加边a->c。然后就转化成了最小路径覆盖问题&#xff08;最小不相交路径覆盖问题&#xff09;。 最小路径覆盖数: 对于一个DAG&…

子段乘积(逆元费马小定理)+线段树做法

题解&#xff1a;一开始做这个题的时候想过尺取法&#xff0c;但是因为没有逆元的知识&#xff0c;不知道该如何不断删除左端元素。其实这题并不难想&#xff0c;设l&#xff0c;r为两端开始都置为1&#xff0c;当长度小于k的时候不断乘右端元素并取余&#xff0c;当长度等于k时…

javascript --- 事件托付

javascript 之 事件托付 长处&#xff1a;1、提高性能&#xff08;仅仅须要对父级进行操作&#xff0c;子节点相同会拥有其相关属性和方法&#xff09; 2、对于新加入的事件。也让其拥有父级事件的属性 <!doctype html> <html lang"en"> <head><…

很多程序员编程时都戴耳机?他们在听什么

&#xff08;给视学算法加星标&#xff09;转自&#xff1a;网络听说很多程序员工作时都戴耳机&#xff1f;他们在听什么呢&#xff1f;观点一&#xff1a;非诚勿扰&#xff0c;想静静1、啥也没听&#xff0c;只是带着耳机而已。只是想告诉别人不要打扰我&#xff0c;选择性屏蔽…

线段树 ---- CF452F. Permutation(线段树维护序列Hash)

题目链接 题目大意&#xff1a; 就是给你一个全排列&#xff0c;问你是否存在一个cab2c\frac{ab}{2}c2ab​ 满足ccc的位置在a,ba,ba,b之间 解题思路&#xff1a; 首先我们先按顺序遍历&#xff0c;我们假设遍历到的数是中间那个数就是ccc,那么它要存在的答案的话就是存在一个…

到底是什么特征影响着CNN的性能?

作者 | 刘畅 编辑 | Jane出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;开门见山。最近阅读了一篇论文&#xff0c;加上看了一些之前的工作。记录一下&#xff0c;CNN 到底学到了什么东西&#xff0c;或者换句话讲。到底是什么样的特征在影响着CNN 的性能&#xff1…