• CF1103D Professional layer 状压DP


    传送门


    首先对于所有数求gcd并求出这个gcd含有的质因子,那么在所有数中,只有这一些质因子会对答案产生影响,而且对于所有的数,每一个质因子只会在一个数中被删去。

    质因子数量不会超过(11),所以考虑暴力的状压DP:设(f_{i,j,k})表示前(i)个数中选出(j)个数并删去了集合为(k)的质因子的最小代价,转移枚举子集并计算转移是否合法(即第(i)个数中当前集合质因子的乘积是否超过(K)),复杂度(O(nm3^m))

    考虑优化:对每一个数将不能对答案造成影响的因子全部丢掉。对于剩下的数相同的一些数,最多只会选按权值从小到大排序之后前质因子个数个产生贡献。

    再加上一些奇怪的优化就可以快很多了。时间复杂度(O(?m3^m))

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    #include<map>
    //This code is written by Itst
    using namespace std;
    
    #define int long long
    inline int read(){
    	int a = 0;
    	char c = getchar();
    	while(!isdigit(c))
    		c = getchar();
    	while(isdigit(c)){
    		a = a * 10 + c - 48;
    		c = getchar();
    	}
    	return a;
    }
    
    inline int gcd(int a , int b){
    	int r = a % b;
    	while(r){a = b; b = r; r = a % b;}
    	return b;
    }
    
    #define st first
    #define nd second
    const int MAXN = 1e6 + 7;
    struct zt{
    	int num , w;
    	bool operator <(const zt a)const{return w < a.w;}
    }now[MAXN];
    vector < int > in;
    int N , K , allGcd , dp[12][1 << 11] , calc[1 << 11];
    map < int , vector < int > > lsh;
    
    signed main(){
    #ifndef ONLINE_JUDGE
    	freopen("in","r",stdin);
    	//freopen("out","w",stdout);
    #endif
    	N = read(); K = read();
    	for(int i = 1 ; i <= N ; ++i){
    		now[i].num = read();
    		allGcd = gcd(allGcd , now[i].num);
    	}
    	for(int i = 1 ; i <= N ; ++i) now[i].w = read();
    	if(allGcd == 1) return puts("0") , 0;
    	for(int i = 2 ; i <= 1e6 && 1ll * i * i <= allGcd ; ++i)
    		if(allGcd % i == 0){
    			in.push_back(i);
    			while(allGcd % i == 0) allGcd /= i;
    		}
    	if(allGcd - 1) in.push_back(allGcd);
    	int M = in.size();
    	for(int i = 1 ; i <= N ; ++i){
    		int z = 1;
    		for(auto j : in)
    			while(now[i].num % j == 0){
    				now[i].num /= j;
    				z *= j;
    			}
    		lsh[z].push_back(now[i].w);
    	}
    	memset(dp , 2 , sizeof(dp));
    	dp[0][0] = 0;
    	for(auto t : lsh){
    		int x = t.st;
    		sort(t.nd.begin() , t.nd.end());
    		if(t.nd.size() > M) t.nd.resize(M);
    		vector < int > num;
    		for(int i = 0 ; i < 1 << M ; ++i){
    			int times = 1 , p = x;
    			for(int j = 0 ; j < M ; ++j)
    				if(i & (1 << j))
    					while(p % in[j] == 0){
    						p /= in[j];
    						times *= in[j];
    					}
    			num.push_back(times);
    		}
    		for(auto p : t.nd){
    			bool flg = 0;
    			for(int i = M - 1 ; i >= 0 ; --i)
    				for(int j = 0 ; j < 1 << M ; ++j)
    					if(dp[i][j] <= 1e12){
    						int all = (1 << M) - 1 - j;
    						for(int k = all ; k ; k = (k - 1) & all)
    							if(num[k] <= K)
    								if(dp[i + 1][j | k] > dp[i][j] + p){
    									dp[i + 1][j | k] = dp[i][j] + p;
    									flg = 1;
    								}
    					}
    			if(!flg) break;
    		}
    	}
    	int minN = 1e18;
    	for(int i = 1 ; i <= M ; ++i)
    		minN = min(minN , dp[i][(1 << M) - 1] * i);
    	if(minN > 1e12) cout << -1;
    	else cout << minN;
    	return 0;
    }
    
  • 相关阅读:
    在浏览器地址栏输入url的后的过程
    webpack的理解
    Vuex总结
    vue 中引用better-scroller实现横向轮播
    vue中类似于jq中的ele.addClass('class').siblings().removeClass('class')效果
    vue中星级判断函数
    ---redux---
    ---react-redux----
    ----flux----
    React组件
  • 原文地址:https://www.cnblogs.com/Itst/p/10472688.html
Copyright © 2020-2023  润新知