https://codeforces.com/problemset/problem/1322/C
快乐
核心在于 gcd(a,b) == gcd(a+b,a,b)
加法不会影响和的gcd,所以本质就不是那么多了
既然是gcd,那就枚举出左边尽可能不重合的右边权值的GCD吧,
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#include<sstream>
#include<string>
#include<map>
using namespace std;
const int maxn = 2e6+11;
const int N = 5e5+11;
typedef long long ll;
string sn;
string cal(int x){
string a;
while(x){ int t = x%10 + '0';a.push_back(t);x/=10;}
return a;
}
vector<string>ans;
map<string,ll>cns;
vector<int>G[maxn],ins[maxn];
void add(int be,int en){
G[be].push_back(en);
}
ll list[maxn];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++) {
G[i].clear(),ins[i].clear();
list[i] = 0;
G[i+N].clear();
}
for(int i=1;i<=n;i++){
scanf("%lld",&list[i]);
}
for(int i=0;i<m;i++){
int be,en;
scanf("%d%d",&be,&en);
be += N;
add(en,be);
}
for(int i=1;i<=n;i++){
for(int j=0;j<G[i].size();j++){
int p = G[i][j];
ins[i].push_back(p-N);
}
}
ans.clear();
cns.clear();
for(int i=1;i<=n;i++){
sort(ins[i].begin(),ins[i].end());
sn.clear();
for(int j=0;j<ins[i].size();j++){
int p = ins[i][j];
sn += cal(p);
sn += "#";
}
if(sn.size() == 0) continue;
ans.push_back(sn);
cns[sn] += list[i];
}
ll d;
for(int i=0;i<ans.size();i++){
if(i == 0) d = cns[ans[i]];
else{
d = __gcd(d,cns[ans[i]]);
}
}
printf("%lld
",d);
}
return 0;
}