https://codeforces.com/contest/1493/problem/D
被现场一车人过掉的题卡了一万年,一开始直接线段树合并质因数求gcd nlog^3n 超时了
后来发现我们关心的质因数事实上很少,必须要每个数字都有才行
那么用s[num]这个set维护每个数字num这个因数有多少次幂,s[num].size()=n时,才会被加到答案里
用sa[i]维护i这个数字的所有质因数和幂数
每次添加就相当于log次修改sa[i]和s[num],所以,总复杂度是O(nlog^2n)
注意要答案边维护向上乘多的数字,而不是每次算一遍,会被卡常。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=2e5+10;
const int mod=1e9+7;
int n,q;
int a[maxl],mip[maxl],p[maxl];
typedef pair<int,int> pr;
set<pr> s[maxl],sa[maxl];
bool no[maxl];
set<pr> ::iterator it,it2;
inline void shai()
{
for(int i=2;i<maxl;i++)
{
if(!no[i]) p[++p[0]]=i,mip[i]=i;
int j=1,t=p[j]*i;
while(j<=p[0] && t<maxl)
{
no[t]=true;mip[t]=p[j];
if(i%p[j]==0)
break;
t=p[++j]*i;
}
}
}
inline set<pr> div(int x)
{
set<pr> ret;
while(x>1)
{
int d=mip[x],cnt=0;
while(x%d==0)
x/=d,cnt++;
ret.insert({d,cnt});
}
return ret;
}
inline void prework()
{
shai();
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]),sa[i]=div(a[i]);
for(pr j:sa[i])
s[j.first].insert({j.second,i});
}
}
inline ll qp(ll a,ll b)
{
ll ans=1,cnt=a;
while(b)
{
if(b&1) ans=ans*cnt%mod;
cnt=cnt*cnt%mod;
b>>=1;
}
return ans;
}
inline void mainwork()
{
set<pr> ans,tmp;ll res=1;
for(pr j:sa[1])
if((int)s[j.first].size()==n)
{
int cnt=(*s[j.first].begin()).first;
ans.insert({j.first,cnt});res=res*qp(j.first,cnt)%mod;
}
for(int i=1;i<=q;i++)
{
int id,x;
scanf("%d%d",&id,&x);
tmp=div(x);
for(pr j:tmp)
{
int num=j.first,cnt=j.second;
it=sa[id].lower_bound({num,0});
if(it==sa[id].end() || (*it).first!=num)
{
sa[id].insert(j);
s[num].insert({cnt,id});
if((int)s[num].size()==n)
{
pr q=(*s[num].begin());
ans.insert({num,q.first});
res=res*qp(num,q.first)%mod;
}
}
else
{
int ncnt=cnt+(*it).second;
s[num].erase(s[num].lower_bound({(*it).second,id}));
sa[id].erase(it);
sa[id].insert({num,ncnt});
s[num].insert({ncnt,id});
if((int)s[num].size()==n)
{
pr q=(*s[num].begin());
it2=ans.lower_bound({num,0});
if(it2!=ans.end() && (*it2).first==num)
ans.erase(it2),res=res*qp(num,q.first-(*it2).second)%mod;
else
res=res*qp(num,q.first)%mod;
ans.insert({num,q.first});
}
}
}
printf("%lld\n",res);
}
}
int main()
{
prework();
mainwork();
return 0;
}