1. 程式人生 > 實用技巧 >2020CCPC Weihai Site L.Clock Mater 數論,分組揹包

2020CCPC Weihai Site L.Clock Mater 數論,分組揹包

2020CCPC Weihai Site L.Clock Mater 數論,揹包

題意

抽象出來就是給定\(n\),構造出最大的\(LCM(x_1 * x_2 *x_3....)\)\(x_1 + x_2 + x_3 ... = n\)

\[1\leq T \leq 30000\\ 1\leq b \leq 30000 \]

對答案輸出用\(ln(ans)\)

分析

考慮最後加起來的\(x\),肯定希望這些數互質,這樣就要求每個數唯一分解後形如\(p^\alpha\)

由於題給的範圍比較小,所以我們希望能列舉所有指數的情況,這個時候就用分組揹包即可

價值即\(log(x)\)

複雜度\(O(n^2logn)\)

注意點:計算每個數的對數有太多不必要的時間,可以預處理出\(ln\)

賽時沒做出這題,實在是不應該

程式碼

const int maxn = 1e5 + 5;
int cnt;
int prime[maxn];
int vis[maxn];

void euler_sieve() {
	cnt = 0;
	for (int i = 2; i <= maxn; i++) {
		if (!vis[i]) {
			prime[++cnt] = i;
		}
		for (int j = 1; j <= cnt; j++) {
			if (i * prime[j] > maxn) break;
			vis[i * prime[j]] = 1;
			if (i % prime[j] == 0) break;
		}
	}
}

double dp[30010];
double lg[30010];
const int M = 30010;
void init() {
	for (int i = 0; i < M; i++)
		lg[i] = log(i);
	for (int i = 1; i <= cnt; i++)
		for (int j = M - 1; j >= prime[i]; j--)
			for (int k = prime[i]; k <= j; k *= prime[i])
				dp[j] = max(dp[j], dp[j - k] + lg[k]);
}

void solve() {
	int n = rd();
	printf("%.10f\n", dp[n]);
}

int main() {
	euler_sieve();
	init();
	int T = rd();
	while (T--)
		solve();
}