2020CCPC威海L.Clock Master(质数预处理+分组背包)

8 篇文章 0 订阅

题目链接:http://codeforces.com/gym/102798/problem/L
题意:给一个b,要求将b分成任意n个数ti,使得(k%t1,k%t2,…,k%tn)的组合数最多。
解题思路:
(k%t1,k%t2,…,k%tn)的组合数可以发现是t1.t2…tn的最小公倍数,因为只有k经过最小公倍数次,才能会到最开始的(0,0,0,…,0)状态。所以这个题目就变成了求最小公倍数最大的题目。
要求最小公倍数最大,那么就要求充分利用b内的数,要求拆分后的数两两互质,如果a与b不互质,那么就会浪费一个a和b的最大公因子,比如a=3,b=9的时候,3和9同时出现的话,那么产生的影响也只有9,3不会起作用。
所以这里就用到了分组背包的思想,将不互质(互斥)的放在同一组背包中,然后进行分组背包。
PS:这题需要直接预处理30000范围的情况,否则会超时

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<map>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<string.h>

using namespace std;
const int MAXN = 3e4+10;

int t;
int b;

double dp[31000];
double lg[31000];
int prime[MAXN + 1];

void getPrime() {
	memset(prime, 0, sizeof(prime));
	for (int i = 2; i <= MAXN; i++) {
		if (!prime[i])prime[++prime[0]] = i;
		for (int j = 1; j <= prime[0] && prime[j] <= MAXN / i; j++) {
			prime[prime[j] * i] = 1;
			if (i % prime[j] == 0) break;

		}
	}
}
void init() {
	getPrime();
	for (int i = 1; i <= MAXN; i++) {
		lg[i] = log(1.0 * i);
		dp[i] = 0;
	}
	dp[0] = 0;
	for (int i = 1; i <= prime[0]; i++) {
		for (int j = 30000; j >= prime[i]; j--) {
			for (int k = prime[i]; k <= 30000; k*=prime[i]) {
				if (j >= k) {
					dp[j] = max(dp[j], dp[j - k]+lg[k]);
				}
			}
		}
	}
}
int main() {
	init();
	cin >> t;
	while (t--) {
		cin >> b;
		printf("%.6f\n",dp[b]);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Buyi.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值