CF1103D Professional layer
CF1103D Professional layer
好题。
首先考虑分解质因数,对于每个有重质因数,找一些数将指数消成 。
好像分解不了那么多?发现有效质数集只能是 ,且不同质因子个数最多 个。
状压就行了,记 表示选 个数,消了 的质数集合的最小花费。
注意到每次选一个数必定消掉一个新的质数,故第一维大小只有 ,即最多选 个数,所以每种数都保留最便宜的 个。(记与能取得最大 的倍数的相同的 为一类数)
暴力发现 个质数所有的指数幂组合方式最多 个,记为 。
所以我们首先枚举组合方式,内层嵌套枚举对应的最便宜的 的花费。
转移时先枚举选几个数,当前消的状态,以及准备消哪些质数。
时间复杂度 。
#include <cstdio>
#include <vector>
#include <unordered_map>
#include <cstring>
#include <algorithm>
typedef long long ll;
#define ha putchar(' ')
#define he putchar('\n')
inline ll read() {
ll x = 0;
char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return x;
}
inline void write(ll x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9)
write(x / 10);
putchar(x % 10 + 48);
}
const int _ = 1e6 + 1;
int n, m;
ll k, f[12][1 << 11], ans = 1e18;
std::pair<ll, ll> c[_];
std::vector<ll> a, d;
std::unordered_map<ll, std::vector<ll>> mp;
ll gcd(ll a, ll b)
{
return b ? gcd(b, a % b) : a;
}
signed main() {
n = read(), k = read();
ll nw = 0;
for (int i = 1; i <= n; ++i) c[i].first = read(), nw = gcd(nw, c[i].first);
for (int i = 1; i <= n; ++i) c[i].second = read();
if (nw == 1) return write(0), he, 0;
for (int i = 2; 1ll * i * i <= nw; ++i)
if (!(nw % i)) {
d.emplace_back(i);
while (!(nw % i)) nw /= i;
}
if (nw != 1) d.emplace_back(nw);
m = d.size();
for (int i = 1; i <= n; ++i) {
ll z = 1;
for (ll j : d)
while (!(c[i].first % j)) c[i].first /= j, z *= j;
mp[z].emplace_back(c[i].second);
}
memset(f, 2, sizeof f);
f[0][0] = 0;
for (auto t : mp) {
sort(t.second.begin(), t.second.end());
a.clear();
for (int i = 0; i < (1 << m); ++i) {
ll z = 1, nw = t.first;
for (int j = 0; j < m; ++j)
if (i & (1 << j)) while (!(nw % d[j])) nw /= d[j], z *= d[j];
a.emplace_back(z);
}
for (ll r : t.second) {
bool flg = 0;
for (int i = m - 1; i >= 0; --i)
for (int j = 0; j < (1 << m); ++j) {
int tmp = (1 << m) - j - 1;
for (int p = tmp; p; p = (p - 1) & tmp)
if (a[p] <= k && f[i + 1][j | p] > f[i][j] + r) f[i + 1][j | p] = f[i][j] + r, flg = 1;
}
if (!flg) break;
}
}
for (int i = 1; i <= m; ++i) ans = std::min(ans, f[i][(1 << m) - 1] * i);
write(ans > 1e12 ? -1 : ans), he;
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18121968