题意:
给出一个长度为 n n n 数组,和 q q q 次操作,每次操作将 第 i i i 位的数乘上 x x x ,然后输出全部数的 g c d gcd gcd 。
题解:
可以将 g c d gcd gcd 考虑成每个质数的贡献,即所有数分解后质数的最低次幂。
先预处理出n个数分解后质数有多少次幂,用 m a p map map 存一下, m p [ i ] [ j ] mp[i][j] mp[i][j] 表示第 i i i 个数分解后质数 j j j 有多少次幂。
然后再用 m u l t i s e t multiset multiset 存每个质数分别在 1 1 1 到 n n n 里面出现了几次,即 s e t [ i ] set[i] set[i] 里面存了这n个数分解后 i i i 有多少次幂。
这样 s e t set set 里面的首元素就是对答案的贡献次幂。
然后再考虑 q q q 个操作:
也是先对 x x x 进行质因数分解,然后修改第 i i i 个数的质数的次幂和 m u l t i s e t multiset multiset 里面的值,再考虑对 g c d gcd gcd 的贡献即可。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=2e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int prime[MAXN],cnt;
int isprime[MAXN];
multiset<int>p[MAXN];
map<int,int>mp[MAXN];
int a[MAXN];
void getprime(int n)
{
for(ll i=2;i<=n;i++)
{
if(!isprime[i])
{
prime[++cnt]=i;
isprime[i]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
{
isprime[i*prime[j]]=prime[j];
if(i%prime[j]==0) break;
}
}
}
ll qpow(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1) res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
int main()
{
getprime(2e5);
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
int temp=a[i];
while(temp!=1)
{
mp[i][isprime[temp]]++;
temp/=isprime[temp];
}
temp=a[i];
int pre=isprime[temp];
while(temp!=1)
{
if(isprime[temp]!=pre)
{
p[pre].insert(mp[i][pre]);
}
pre=isprime[temp];
temp/=isprime[temp];
}
if(pre)
{
p[pre].insert(mp[i][pre]);
}
}
ll ans=1;
for(int i=1;i<=cnt;i++)
{
if(p[prime[i]].size()==n)
{
ans=ans*(qpow(prime[i],*p[prime[i]].begin()))%mod;
}
}
while(q--)
{
int op,x;
scanf("%d%d",&op,&x);
int temp=x;
int pre=isprime[temp];
int cnt=0;
while(temp!=1)
{
if(pre!=isprime[temp])
{
if(mp[op].count(pre)==0)
{
mp[op][pre]+=cnt;
p[pre].insert(cnt);
if(p[pre].size()==n)
{
ans=ans*(qpow(pre,*p[pre].begin()))%mod;
}
}
else
{
int last=*p[pre].begin();
p[pre].erase(p[pre].lower_bound(mp[op][pre]));
mp[op][pre]+=cnt;
p[pre].insert(mp[op][pre]);
int now=*p[pre].begin();
if(p[pre].size()==n&&now>last)
{
ans=ans*(qpow(pre,now-last))%mod;
}
}
cnt=0;
}
pre=isprime[temp];
cnt++;
temp/=isprime[temp];
}
if(pre)
{
if(mp[op].count(pre)==0)
{
mp[op][pre]+=cnt;
p[pre].insert(cnt);
if(p[pre].size()==n)
{
ans=ans*(qpow(pre,*p[pre].begin()))%mod;
}
}
else
{
int last=*p[pre].begin();
p[pre].erase(p[pre].lower_bound(mp[op][pre]));
mp[op][pre]+=cnt;
p[pre].insert(mp[op][pre]);
int now=*p[pre].begin();
if(p[pre].size()==n&&now>last)
{
ans=ans*(qpow(pre,now-last))%mod;
}
}
}
printf("%lld\n",ans);
}
}