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;
}
标签:POI2012ODL,Distance,cnt,res,rep,second,mx,first
From: https://www.cnblogs.com/xiaruize/p/18156734