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; }