POI2012ODL-Distance

xiaruize發表於2024-04-25

POI #Year2012 #數學

\(cnt(x)\)\(x\) 的因子個數

\(d(i,j)=cnt(a_i)+cnt(a_j)-2cnt(gcd(i,j))\)

列舉 \(i\) ,剩下的時間複雜度可以列舉 \(gcd\) ,考慮此時應該貪心的取 \(cnt(a_j)\) 最小的 \(j\)

這樣不能保證列舉的 \(gcd=gcd(a_i,a_j)\) 但是在 \(gcd=gcd(a_i,a_j)\) 的時候可以取到最小值,所以等價

// Author: xiaruize
const int N = 1e5 + 10;
const int M = 1e6 + 10;

int n;
int a[N];
int cnt[M];
pii mx[M][2];
pii res[N];
vector<int> pr;

void init()
{
	// cnt[1] = 1;
	rep(i, 2, 1e6)
	{
		if (!cnt[i])
		{
			cnt[i] = 1;
			pr.push_back(i);
		}
		for (auto v : pr)
		{
			if (v * i > 1e6)
				break;
			cnt[v * i] = cnt[i] + 1;
			if (i % v == 0)
				break;
		}
	}
}

void upd(int x, pii v)
{
	if (v.first < mx[x][0].first || (v.first == mx[x][0].first && v.second < mx[x][0].second))
	{
		mx[x][1] = mx[x][0];
		mx[x][0] = v;
	}
	else if (v.first < mx[x][1].first || (v.first == mx[x][1].first && v.second < mx[x][1].second))
		mx[x][1] = v;
}

void chkmi(pii &x, pii y)
{
	if (x.first > y.first || (x.first == y.first && x.second > y.second))
		x = y;
}

void solve()
{
	init();
	cin >> n;
	rep(i, 1, n) cin >> a[i];
	mms(mx, 0x3f);
	mms(res, 0x3f);
	rep(i, 1, n)
	{
		rep(j, 1, a[i])
		{
			if (j * j > a[i])
				break;
			if (a[i] % j != 0)
				continue;
			upd(j, {cnt[a[i]], i});
			if (j * j != a[i])
				upd(a[i] / j, {cnt[a[i]], i});
		}
	}
	rep(i, 1, n) debug(i, mx[i]);
	rep(i, 1, n)
	{
		rep(j, 1, a[i])
		{
			if (j * j > a[i])
				break;
			if (a[i] % j != 0)
				continue;
			if (mx[j][0].second == i)
				chkmi(res[i], {mx[j][1].first + cnt[a[i]] - cnt[j] * 2, mx[j][1].second});
			else
				chkmi(res[i], {mx[j][0].first + cnt[a[i]] - cnt[j] * 2, mx[j][0].second});
			if (j * j != a[i])
			{
				if (mx[a[i] / j][0].second == i)
					chkmi(res[i], {mx[a[i] / j][1].first + cnt[a[i]] - cnt[a[i] / j] * 2, mx[a[i] / j][1].second});
				else
					chkmi(res[i], {mx[a[i] / j][0].first + cnt[a[i]] - cnt[a[i] / j] * 2, mx[a[i] / j][0].second});
			}
		}
	}
	rep(i, 1, n)
	{
		debug(res[i]);
		cout << res[i].second << endl;
	}
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	// cin >> testcase;
	while (testcase--)
		solve();
#ifndef ONLINE_JUDGE
	cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
	cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
	return 0;
}