【2025年菜鸟秋招(算法岗)-8月26日-第一题(100分)- 小苯的数字权值】(题目+思路+Java&C++&Python解析+在线测试)

题目内容

定义正整数 nnn 的权值为 nnn 的正因子的数量,即 wt(n)=r(n)wt(n)=r(n)wt(n)=r(n)

其中 r(n)r(n)r(n) 表示 nnn 的因子个数。

给定一个正整数 xxx ,你可以将 xxx 分解为若干个大于 111 的正整数 p1,p2,...,p(k≥1)p_1,p_2,...,p(k≥1)p1,p2,...,p(k1) ,要求

  • p1×p2×...×pk=xp_1×p_2×...×p_k=xp1×p2×...×pk=x

  • 最大化 ∑i=1kwt(pi)\sum^k_{i=1}wt(p_i)i=1kwt(pi)

请你求出在最优分解下,上述表达式的最大可能值。

输入描述

第一行输入一个整数 T(1≤T≤104)T(1 ≤ T ≤ 10^4)T(1T104) 表示测试数据组数。

此后 TTT 行,每行输入一个整数 x(2≤x≤2×105)x(2 ≤x≤2×10^5)x(2x2×105)

输出描述

对于每组数据,在一行上输出对应的最大权值和。

样例1

输入

3
2
10
123

输出

2
4
4

说明

  • 对于 x=2x = 2x=2 ,无法再分解,只能取自身,wt(2)=2wt(2)= 2wt(2)=2

  • 对于 x=10x=10x=10 ,最优方案为 10=2×510=2×510=2×5wt(2)=2,wt(5)=2wt(2)=2,wt(5)=2wt(2)=2wt(5)=2 ,总和 2+2=42+2=42+2=4

  • 对于 x=123x=123x=123 ,最优方案为 123=3×41,wt(3)=2,wt(41)=2123=3×41,wt(3)=2,wt(41)=2123=3×41,wt(3)=2wt(41)=2 ,总和 444

题目解析

核心结论

x=∏i=1mqiaix=\prod_{i=1}^{m} q_i^{a_i}x=i=1mqiai 为质因数分解,令 A=max⁡aiA=\max a_iA=maxai,并定义每一层的计数 在这里插入图片描述

最优答案为

在这里插入图片描述

算法

  • 步骤 111:用试除法分解 xxx,得到所有幂次 aia_iai

  • 步骤 222:计算 τ(x)=∏(ai+1)\tau(x)=\prod (a_i+1)τ(x)=(ai+1)

  • 步骤 333:计算 A=max⁡aiA=\max a_iA=maxai,并按层求和在这里插入图片描述
    其中
    在这里插入图片描述

  • 步骤 444:输出两者较大值。

  • 若输入可能出现 x=1x=1x=1,由于无合法分解(因子需大于 111),可输出 000

C++

#include <bits/stdc++.h>
using namespace std;
using u64 = unsigned long long;

// 试除分解:只返回各质因子的幂次
static vector<int> factor_exps(u64 n) {
	vector<int> exps;
	if (n % 2 == 0) {
		int c = 0;
		while (n % 2 == 0) { n /= 2; ++c; }
		exps.push_back(c);
	}
	for (u64 p = 3; p <= n / p; p += 2) {
		if (n % p == 0) {
			int c = 0;
			while (n % p == 0) { n /= p; ++c; }
			exps.push_back(c);
		}
	}
	if (n > 1) exps.push_back(1);
	return exps;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int T;
	if (!(cin >> T)) return 0;
	while (T--) {
		u64 x; cin >> x;
		if (x == 1) { cout << 0 << '\n'; continue; } // 若题面保证 x>=2,可删除
		vector<int> exps = factor_exps(x);

		// 计算 tau(x) = ∏(a_i+1)
		u64 tau = 1;
		for (int a : exps) tau *= (u64)(a + 1);

		// 计算分层和 ∑ 2^{r_ell}
		int A = 0;
		for (int a : exps) A = max(A, a);
		u64 layerSum = 0;
		for (int ell = 1; ell <= A; ++ell) {
			int r = 0;
			for (int a : exps) if (a >= ell) ++r;
			layerSum += (1ULL << r);
		}

		cout << max(tau, layerSum) << '\n';
	}
	return 0;
}

Python

import sys

def factor_exps(n: int):
	# 返回各质因子幂次
	exps = []
	if n % 2 == 0:
		c = 0
		while n % 2 == 0:
			n //= 2
			c += 1
		exps.append(c)
	p = 3
	while p * p <= n:
		if n % p == 0:
			c = 0
			while n % p == 0:
				n //= p
				c += 1
			exps.append(c)
		p += 2
	if n > 1:
		exps.append(1)
	return exps

def solve():
	data = sys.stdin.read().strip().split()
	if not data: return
	it = iter(data)
	T = int(next(it))
	for _ in range(T):
		x = int(next(it))
		if x == 1:
			print(0)
			continue
		exps = factor_exps(x)

		# tau(x)
		tau = 1
		for a in exps:
			tau *= (a + 1)

		# 分层和
		A = max(exps) if exps else 0
		layer_sum = 0
		for ell in range(1, A + 1):
			r = sum(1 for a in exps if a >= ell)
			layer_sum += (1 << r)

		print(max(tau, layer_sum))

if __name__ == "__main__":
	solve()

Java

import java.io.*;
import java.util.*;

public class Main {
	static ArrayList<Integer> factorExps(long n) {
		// 返回各质因子的幂次
		ArrayList<Integer> exps = new ArrayList<>();
		if (n % 2 == 0) {
			int c = 0;
			while (n % 2 == 0) { n /= 2; c++; }
			exps.add(c);
		}
		for (long p = 3; p <= n / p; p += 2) {
			if (n % p == 0) {
				int c = 0;
				while (n % p == 0) { n /= p; c++; }
				exps.add(c);
			}
		}
		if (n > 1) exps.add(1);
		return exps;
	}

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine().trim());
		StringBuilder sb = new StringBuilder();
		while (T-- > 0) {
			long x = Long.parseLong(br.readLine().trim());
			if (x == 1) { sb.append(0).append('\n'); continue; }
			ArrayList<Integer> exps = factorExps(x);

			// tau(x) = ∏(a_i+1)
			long tau = 1;
			for (int a : exps) tau *= (a + 1L);

			// 分层和 ∑ 2^{r_ell}
			int A = 0;
			for (int a : exps) A = Math.max(A, a);
			long layerSum = 0;
			for (int ell = 1; ell <= A; ++ell) {
				int r = 0;
				for (int a : exps) if (a >= ell) r++;
				layerSum += (1L << r);
			}
			sb.append(Math.max(tau, layerSum)).append('\n');
		}
		System.out.print(sb.toString());
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

塔子哥学算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值