传送门
题意: 给nnn个数,让后qqq个操作,每次选择一个位置的数使其乘xxx,每次询问后输出所有数的gcdgcdgcd。
思路: 这个题思路算是比较好想的。首先就是一个计算方式即计算所有数的gcdgcdgcd,这个比较容易想到当一个质因数xxx在每个数出现次数>=1>=1>=1的时候,设出现幂数是c1,c2,...,cnc_1,c_2,...,c_nc1,c2,...,cn,他对gcdgcdgcd的贡献为xmin(c1,c2,...,cn)x^{min(c_1,c_2,...,c_n)}xmin(c1,c2,...,cn)。让后对于乘操作,可以发现gcdgcdgcd是单调不减的,所以我们可以递推下去。让后比较显然的就是维护每个质因子在数组nnn中出现的次数,每次取minminmin,让后就会想到对于每个质因子建一颗线段树,但是显然是不行的,空间直接炸掉了。所以需要考虑用其他东西维护,题解是用multisetmultisetmultiset维护的,stlstlstl真香 。
让后就是实现的细节了,当multisetmultisetmultiset的大小为nnn的时候才能更新,更新的时候取最小值,由于multisetmultisetmultiset是自己排序的,所以直接取头部的元素即可。让后更新的时候需要看看是否之前已经更新了一部分mimimi,如果更新过了要从mi+1mi+1mi+1到cntcntcnt更新。
还是对multisetmultisetmultiset不熟悉,比赛想到了用但是不会用 。
最后优化的一点就是lognlognlogn分解质因子。
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,q;
int a[N],nt[N];
multiset<int>s[N];//s[i]表示质因子i在数组中的分布
map<int,int>mp[N];//mp[i][j]表示第i个数的质因子j的个数
bool st[N];
LL ans=1;void add(int id,int x)
{while(x!=1){int div=nt[x],cnt=0;while(div==nt[x]) cnt++,x/=nt[x];int mi;if(s[div].size()==n) mi=*s[div].begin();else mi=0;if(mp[id][div]==0){s[div].insert(cnt),mp[id][div]+=cnt;if(s[div].size()==n){int cnt=*(s[div].begin());for(int i=mi+1;i<=cnt;i++) ans=ans*div%mod;}}else{int t=mp[id][div]; mp[id][div]+=cnt;s[div].erase(s[div].find(t));s[div].insert(mp[id][div]);if(s[div].size()==n){int cnt=*(s[div].begin());for(int i=mi+1;i<=cnt;i++) ans=ans*div%mod;}}}
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);for(int i=2;i<N;i++){if(st[i]) continue;nt[i]=i;for(int j=i+i;j<N;j+=i)st[j]=true,nt[j]=i;}scanf("%d%d",&n,&q);for(int i=1;i<=n;i++){int x; scanf("%d",&x);add(i,x);}while(q--){int x,id; scanf("%d%d",&id,&x);add(id,x);printf("%lld\n",ans);}return 0;
}
/**/