傳送門
題意: 給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分解質因子。
#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
;
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
];
map
<int,int>mp
[N
];
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()
{
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;
}
總結
以上是生活随笔為你收集整理的Codeforces Round #705 (Div. 2) D. GCD of an Array 质因子分解 + stl维护的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。