zoukankan      html  css  js  c++  java
  • [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 ot| 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
    " , ans);
         return 0;
    }
    
  • 相关阅读:
    pat乙级1018
    下拉框多选,出现这种情况,求大神帮我看看
    Filter 过滤器
    拦截器和过滤器区别
    Servlet 生命周期
    cannot simultaneously fetch multiple bags 问题的解决办法
    JPA规范及其它持久层框架
    数据库设计的三大范式
    装饰者模式
    Java 流
  • 原文地址:https://www.cnblogs.com/evenbao/p/14469057.html
Copyright © 2011-2022 走看看