题目内容
定义正整数 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(k≥1) ,要求
-
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(1≤T≤104) 表示测试数据组数。
此后 TTT 行,每行输入一个整数 x(2≤x≤2×105)x(2 ≤x≤2×10^5)x(2≤x≤2×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×5 ,wt(2)=2,wt(5)=2wt(2)=2,wt(5)=2wt(2)=2,wt(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)=2,wt(41)=2 ,总和 444 。
题目解析
核心结论
设 x=∏i=1mqiaix=\prod_{i=1}^{m} q_i^{a_i}x=∏i=1mqiai 为质因数分解,令 A=maxaiA=\max a_iA=maxai,并定义每一层的计数
。
最优答案为
算法
-
步骤 111:用试除法分解 xxx,得到所有幂次 aia_iai。
-
步骤 222:计算 τ(x)=∏(ai+1)\tau(x)=\prod (a_i+1)τ(x)=∏(ai+1)。
-
步骤 333:计算 A=maxaiA=\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());
}
}