悬关求调,RE#12
查看原帖
悬关求调,RE#12
511520
drmr楼主2024/5/29 19:13

萌新求助,一直 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;
}
2024/5/29 19:13
加载中...