[CF1103D] Professional layer

[题目链接]

http://codeforces.com/contest/1103/problem/D

[题解]

\(d = \gcd (a_1, a_2, \dots, a_n) = p_1^{s_1} p_2^{s_2} \dots p_m^{s_m}\) , 其中 \(p_{i}\) 为两两不同的质数。 因为 \(d <= 10 ^ {12}\) , 所以 \(m <= 11\)

首先将每个 \(a_{i}\) 中不属于 \(p_{1} , p_{2} , ... p_{m}\) 的质数次幂去除。 剩下的元素最多有 \(M \leq 11958\) 个 (这个上界当且仅当 \(d = 2 * 3 * 5 * 7 * 11 * 13\))。

修改 \(a_{i}\) 的目标为 : 对于任意 \(1 \leq j \leq m\) , 都存在一个 \(a_{i}\) 满足 \(p_j \not| a_i\)。 为了最小花费 , ,显然对任一 \(d\) 的质因数 \(p_{j}\),我们只需要选择恰好一个 \(a_{i}\),将其修改为不被 \(p_{j}\) 整除即可。

因此我们最多用 \(M\)\(a_{i}\)

从而真正有用的 \(a_{i}\) 只有 \(e_{i}\) 最小的 \(m\) 个, 共有 \(mM\) 个。

不妨令 \(F[i][x][s]\) 表示前 \(i\) 个元素 , 修改了 \(x\) 个 , 且 \(s\) 描述了去除的质因子集合的最小花费。

那么有 : \(F[i][x][s] = \min_{t \subseteq s, t \models a_i} \{ F[i-1][x][s], F[i-1][x-1][s-t]+e_i \}.\)

时间复杂度 : \(O(n \log n+m M 2^m+m^2 3^m)\)

[代码]

#include<bits/stdc++.h>
 
using namespace std;
 
typedef long long LL;
 
#define rep(i , l , r) for (int i = (l); i < (r); ++i)
 
const int MN = 1e6 + 5;
const LL INF = 1e16;
 
LL K;
LL A[MN];
int C[MN];
 
int n;
LL li[30];
int cnt[30] , bak;
map < LL , vector < int > > mi;
map < LL , vector < LL > > ms;
int cl[1 << 11] , cb;
LL dp[12][1 << 11];
 
inline LL gcd(LL x , LL y) {
    return y ? gcd(y , x % y) : x;
}
inline LL chkmin(LL &x , LL y) {
	x = min(x , y);
}
inline void dfs(int S , int mask , LL now , const vector < LL > & vl) {
	if (now > K) return;
	if (S == bak) { cl[cb++] = mask; return; }
	dfs(S + 1 , mask , now , vl);
	dfs(S + 1 , mask | 1 << S , now * vl[S] , vl);
}
 
int main() {
	 
	 scanf("%d%lld" , &n , &K);
	 LL g = 0;
	 for (int i = 1; i <= n; ++i)
	 	 scanf("%lld" , &A[i]) , g = gcd(g , A[i]);
	 for (int i = 1; i <= n; ++i)
	 	 scanf("%d" , &C[i]);
	 LL t = g;
	 for (int i = 2; (LL) i * i <= t; ++i) 
	 	 if (t % i == 0) {
	 	 	 int cc = 0;
			 while (t % i == 0) t /= i , ++cc;
			 li[bak] = i , cnt[bak++] = cc;	
		 }
	 if (t > 1) li[bak] = t , cnt[bak++] = 1;
	 for (int i = 1; i <= n; ++i) {
	 	 vector < LL > tx(bak , 1); t = 1;
	 	 for (int j = 0; j < bak; ++j)
	 	 	 while (A[i] % li[j] == 0)
	 	 	 	 A[i] /= li[j] , t *= li[j] , tx[j] *= li[j];
	 	 if (!mi.count(t)) ms[t] = tx;
	 	 mi[t].emplace_back(C[i]);
	 }
	 for (int i = 0; i <= bak; ++i)
	 for (int j = 0; j < 1 << bak; ++j)
	 	 dp[i][j] = INF;
	 dp[0][0] = 0LL;
	 int U = 1 << bak;
	 for (auto t : ms) {
	 	 dfs(0 , 0 , 1 , t.second);
	 	 vector < int > & lx = mi[t.first];
	 	 sort(lx.begin() , lx.end());
	 	 for (int T = 0; T < lx.size() && T < bak; ++T) {
			 for (int i = bak; i; --i) {
			 	 for (int j = 0; j < cb; ++j) {
			 	 	 int xc = U - 1 - cl[j];
			 	 	 for (int k = xc; ; k = (k - 1) & xc) {
			 	 	 	 if (dp[i - 1][k] != INF)
							chkmin(dp[i][cl[j] | k] , dp[i - 1][k] + lx[T]);
						 if (!k) break;		
					 }
				 }
			 }	 	 	 
		 }
		 cb = 0;
	 }
	 LL ans = INF;
	 for (int i = 0; i <= bak; ++i)
	 	 if (dp[i][U - 1] != INF)
	 	 	 chkmin(ans , dp[i][U - 1] * i);
	 if (ans == INF) ans = -1;
	 printf("%lld\n" , ans);
     return 0;
}
posted @ 2021-03-02 15:11  evenbao  阅读(83)  评论(0编辑  收藏  举报