L Clock Master(2020 China Collegiate Programming Contest Weihai Site)补题

在这里插入图片描述
题意:给你一个数b,求ans = b1 * b2 * b3 …最大,且b = b1+b2+b3…
其实就是求b1 ,b2, b3, b4 的最小公倍数的最大值。
思路:
任意一个数都可以质因数分解成
N = p1a1 * p2a2 * p3a3

所以我们可以这样来想这个问题
j将b看成是一个容量为b的背包;p1a1, p2a2,p3a3…不同的质数的不同次方看成是分成了一个组;这就是一个分组背包的问题了,从质数组中去选择,它们的和不超过b,求它们乘积的最大值。
注意:
①数据范围较大,需要将二维的dp优化为一维的dp
②数据较大,用log进行优化,打表进行处理
log(a*b) =log a + log b,所以状态转移方程为:
在这里插入图片描述
③用欧拉筛求出30010以内的素数。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 30010;
int primes[maxn];
bool vis[maxn];
int cnt;
double dp[maxn];
double logg[maxn];
//欧拉筛素数
void get_prime(){
	for(int i = 2;i <= maxn;i++){
		if(!vis[i]){
			primes[++cnt] = i;
		}
		for(int j = 1;primes[j] * i <= maxn;j++){
			vis[i*primes[j]] = true;
			if(i % primes[j]==0){
				break;
			}
		}
	}
	/*
	for(int i = 1;i<=cnt;i++){
	  cout<<primes[i]<<" ";
	}
	*/
} 
//打表,避免数据过大 
void init(){
	for(int i = 1;i <= maxn;i++){
		logg[i] = log(i);
	//	cout<<logg[i]<<" "; 
	}
	for(int i = 1;i <= cnt;i++){//选择的物品 (质数)
			for(int j = maxn;j >= primes[i];j--){//背包大小 
				for(int k = primes[i];k <= j ;k *= primes[i]){//物品幂次的选择 
					dp[j] = max(dp[j],dp[j-k] + logg[k]);
				     //不选择质数          选择质数(幂次) 
				}
			}
		}
}
int main(){
	get_prime();
	init();
	int t,b;
	cin>>t;
	while(t--){
		cin>>b;
		cout<<fixed<<setprecision(9)<<dp[b]<<endl;
	}
	return 0;
}

(有什么错误就指出来吧hhh…)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值