Codeforces Round #675 (Div. 2) 1442 F - Boring Queries 可持久化線段樹維護 區間乘法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define pb push_back
typedef pair<int,int> pii;
const double PI= acos(-1.0);
const int M = 2e5+7;
const int mod = 1e9+7;
struct node{
int l,r,id,ans;
}p[M];
bool cmp(node a,node b){
return a.r<b.r;
}
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
int m;
int prime[M];//第幾個質數的值
int v[M];//i的最小質數
vector<int>pv[M];//數i的質因子
void gao(int n)//預處理1-n每個數的質因子,方便加速後續處理
{
for(int i=2;i<=n;i++)
{
if(v[i]==0)prime[++m]=i,v[i]=i;
for(int j=1;j<=m&&i*prime[j]<=n;j++)
{
v[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
for(int i=1;i<=m;i++)
for(int j=prime[i];j<=n;j+=prime[i])
pv[j].pb(prime[i]);
}
stack<int>s[M];//質數x ,線上段樹中出現的位置id
int a[M],ans[M];
int rt[M];
//n*logn *logn = 1e5*17*17 2e5 * 200 足夠了!
int tr[M*130];//區間乘積
int ls[M*130],rs[M*130],cnt;
void bd(int &o,int l,int r){
if(!o)o=++cnt;
tr[o]=1;
if(l==r)return ;
int m=(l+r)/2;
bd(ls[o],l,m);
bd(rs[o],m+1,r);
}
//up()
void up(int pre,int &o,int l,int r,int x,int d){//可持久化線段樹
o=++cnt;
tr[o]=tr[pre];
ls[o]=ls[pre];
rs[o]=rs[pre];
tr[o]=(ll)tr[o]*d%mod;
if(l==r)return ;
int m=(l+r)/2;
if(x<=m)up(ls[pre],ls[o],l,m,x,d);
else up(rs[pre],rs[o],m+1,r,x,d);
}
ll qu(int o,int l,int r,int x,int y){
if(x<=l&&r<=y){
return tr[o];
}
int m=(l+r)/2;
ll ans=1;
if(x<=m)ans=ans*qu(ls[o],l,m,x,y)%mod;
if(y>m)ans=ans*qu(rs[o],m+1,r,x,y)%mod;
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
gao(200000);
int n,q;
cin>>n;
bd(rt[0],1,n);//先初始化第一顆樹,方便後面的樹繼承
for(int i=1;i<=n;i++)cin>>a[i];
cin>>m;
for(int i=1;i<=m;i++)
cin>>p[i].l>>p[i].r;
int sz=1;
for(int i=1;i<=n;i++)//列舉右端點
{
rt[i]=rt[i-1];//由於要在當前樹上多次更新,我們先把上棵樹的根繼承過來,然後在這個基礎上更新
int tp=a[i],tm=0,tnm=0;
for(auto x:pv[a[i]]){
tm=0,tnm=0;
while(tp%x==0)tp/=x,tm++;
tnm=tm;
up(rt[i],rt[i],1,n,i,qpow(x,tm));
while(!s[x].empty()&&tm){
up(rt[i],rt[i],1,n,s[x].top(),qpow(x,mod-2));
s[x].pop();tm--;
}
for(int j=1;j<=tnm;j++)s[x].push(i);
}
//qu(1,1,n,j,i) --> (j,i) 中所有數的LCM
}
int lst=0;
for(int i=1;i<=m;i++){
int l,r;
l=(p[i].l+lst)%n+1,r=(p[i].r+lst)%n+1;
if(l>r)swap(l,r);
// cout<<rt[r]<<" - "<<endl;
lst=qu(rt[r],1,n,l,r);
cout<<lst<<endl;
}
return 0;
}
/*
10
10 2 8 8 8 8 8 10 2 3
10
1 2
6 1
4 10
1 9
9 1
6 10
3 3
8 1
4 10
6 7
*/
相關文章
- Codeforces Round #406 (Div. 1) C. Till I Collapse(可持久化線段樹)持久化
- 區間k小值(可持久化線段樹)持久化
- 可持久化線段樹持久化
- 線段樹維護區間等差數列
- P3834 【模板】可持久化線段樹 2持久化
- 樹形dp - Codeforces Round #322 (Div. 2) F Zublicanes and Mumocrates
- hdu 2665 可持久化線段樹求區間第K大值(函式式線段樹||主席樹)持久化函式
- Codeforces Round #406 (Div. 1) B. Legacy(線段樹優化建圖)優化
- Codeforces Round #373 (Div. 1) C. Sasha and Array 線段樹
- Codeforces Round #336 (Div. 2) D 區間dp
- CodeForces 145 E. Lucky Queries(線段樹)
- 「學習筆記」可持久化線段樹筆記持久化
- Codeforces Round 970 (Div. 3)A~F
- 線段樹維護單調棧——區間查詢版本 & 維護遞減序列
- 【資料結構】可持久化線段樹初步資料結構持久化
- 演算法隨筆——主席樹(可持久化線段樹)演算法持久化
- Codeforces 52C (線段樹區間更新)
- Codeforces Round #320 (Div. 2) [Bayan Thanks-Round] D 字首字尾維護
- 【主席樹】P3919 【模板】可持久化線段樹 1持久化
- 可持久化線段————主席樹(洛谷p3834)持久化
- Codeforces Round 987 (Div. 2) (C~F) 題解/個人記錄
- Codeforces Round #371 (Div. 2) C. Sonya and Queries[Map|二進位制]
- Codeforces Round #639 (Div. 2)
- Codeforces Round #541 (Div. 2)
- Codeforces Round #682 (Div. 2)
- Codeforces Round #678 (Div. 2)
- Codeforces Round #747 (Div. 2)
- Codeforces Round #673 (Div. 2)
- Codeforces Round #672 (Div. 2)
- Codeforces Round #448 (Div. 2) A
- Codeforces Round #217 (Div. 2)
- Codeforces Round #256 (Div. 2)
- Codeforces Round #259 (Div. 2)
- Codeforces Round #257 (Div. 2)
- Codeforces Round #258 (Div. 2)
- Codeforces Round #171 (Div. 2)
- Codeforces Round #173 (Div. 2)
- Codeforces Round 951 (Div. 2)