萌新求助,一直 RE 在第 12 个点,求调。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6;
int n, m, dp1[500][500], dp2[500][500], a[N], b[N], Gcd[N], c[N];
vector<int> diva, divb, prea, preb;
vector<pair<int, int> > primea, primeb, ans;
map<int, int> ida, idb;
int gcd(int x, int y){
if(x < y) swap(x, y);
if(x % y) return gcd(y, x % y);
return y;
}
void init(){
memset(dp1, 0, sizeof(dp1));
memset(dp2, 0, sizeof(dp2));
primea.clear(), primeb.clear();
diva.clear(), divb.clear();
prea.clear(), preb.clear();
ida.clear(), idb.clear();
int tmp, now = a[1];
for(int i = 2; i * i <= now; i++){
if(now % i) continue;
tmp = 0; while(now % i == 0) tmp++, now /= i;
primea.push_back(make_pair(i, tmp));
}
if(1 < now) primea.push_back(make_pair(now, 1));
now = b[1];
for(int i = 2; i * i <= now; i++){
if(now % i) continue;
tmp = 0; while(now % i == 0) tmp++, now /= i;
primeb.push_back(make_pair(i, tmp));
}
if(1 < now) primeb.push_back(make_pair(now, 1));
diva.push_back(1); divb.push_back(1);
for(pair<int, int> i : primea){
tmp = diva.size(), now = 1;
for(int j = 1; j <= i.second; j++){
now *= i.first;
for(int k = 0; k < tmp; k++)
diva.push_back(diva[k] * now);
}
prea.push_back(tmp);
}
for(pair<int, int> i : primeb){
tmp = divb.size(), now = 1;
for(int j = 1; j <= i.second; j++){
now *= i.first;
for(int k = 0; k < tmp; k++)
divb.push_back(divb[k] * now);
}
preb.push_back(tmp);
}
now = 0; for(int i : diva) ida[i] = (now++);
now = 0; for(int i : divb) idb[i] = (now++);
return ;
}
void work(bool ifChange){
if(ifChange) swap(a[1], b[1]); init();
// calculate the delta
for(int i = 2; i <= n; i++){
dp1[ida[gcd(a[1], a[i])]][idb[gcd(b[1], b[i])]]++;
dp1[ida[gcd(a[1], b[i])]][idb[gcd(b[1], a[i])]]++;
dp1[ida[gcd(a[1], Gcd[i])]][idb[gcd(b[1], Gcd[i])]]--;
dp2[ida[gcd(a[1], b[i])]][idb[gcd(b[1], a[i])]] += c[i];
dp2[ida[gcd(a[1], Gcd[i])]][idb[gcd(b[1], Gcd[i])]] -= c[i];
}
// try add it up
for(int i = 0; i < primea.size(); i++)
for(int j = diva.size() - 1; j >= 0; j--)
for(int k = divb.size() - 1; !(diva[j] % primea[i].first) && k >= 0; k--)
dp1[j - prea[i]][k] += dp1[j][k];
for(int i = 0; i < primea.size(); i++)
for(int j = diva.size() - 1; j >= 0; j--)
for(int k = divb.size() - 1; !(diva[j] % primea[i].first) && k >= 0; k--)
dp2[j - prea[i]][k] += dp2[j][k];
for(int i = 0; i < primeb.size(); i++)
for(int j = divb.size() - 1; j >= 0; j--)
for(int k = diva.size() - 1; !(divb[j] % primeb[i].first) && k >= 0; k--)
dp1[k][j - preb[i]] += dp1[k][j];
for(int i = 0; i < primeb.size(); i++)
for(int j = divb.size() - 1; j >= 0; j--)
for(int k = diva.size() - 1; !(divb[j] % primeb[i].first) && k >= 0; k--)
dp2[k][j - preb[i]] += dp2[k][j];
// calculate the answer when dp1 >= n - 1 (because you have a[1] and b[1] too)
for(int i = 0; i < diva.size(); i++)
for(int j = 0; j < divb.size(); j++){
if(dp1[i][j] < n - 1) continue;
int now = dp2[i][j], tmp = diva[i] + divb[j];
if(ifChange) now += c[1];
ans.push_back(make_pair(now, tmp));
dp1[i][j] = 0, dp2[i][j] = 0; // remember to do this
}
return ;
}
signed main(){
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
for(int i = 1; i <= n; i++) Gcd[i] = gcd(a[i], b[i]);
for(int i = 1; i <= n; i++) cin >> c[i];
work(0);
work(1);
// binary search the answer
sort(ans.begin(), ans.end());
// the premax because it could have ans[i].second < ans[i + 1].second
for(int i = 1; i < ans.size(); i++)
ans[i].second = max(ans[i].second, ans[i - 1].second);
while(m--){
int q; cin >> q;
int l = 0, r = ans.size() - 1, ANS = -1;
while(l <= r){
int mid = (l + r) >> 1;
if(ans[mid].first <= q) ANS = ans[mid].second, l = mid + 1;
else r = mid - 1;
}
cout << ANS << " ";
}
return 0;
}