美团笔试 美团笔试题 0405
笔试时间:2025年04月05日
历史笔试传送门:
第一题
题目:整数转变
开始有一个整数b ,你需要经过若干次操作,使n 的值不小于m 。 操作一:将n 更改为2 * n ,花费为 w2 ; 操作二:将 n 更改为3 * n ,花费为w3 。 请输出需要的最小花费。
输入描述
输入第一行一个整数T,代表接下来有 T 组测试数据。
接下来 T 行,每行有 4 个整数 n,m,w2,w31< T < 100001< n,m< 2^{31}-11< w_2,w_3 < 1000
输出描述
对于每组测试数据,输出一行,一个整数代表最小花费。
样例输入
4
1 6 2 3
4 32 3 4
2 1 1 2
1 2147483647 1 4
样例输出
5
8
0
31
参考题解
记忆化搜索。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <unordered_map> #include <algorithm> using namespace std; unordered_map<int, int> dp; int m, w2, w3; int dfs(int i) { if (i >= m) return 0; if (dp.count(i)) return dp[i]; int cost2 = dfs(i * 2) + w2; int cost3 = dfs(i * 3) + w3; dp[i] = min(cost2, cost3); return dp[i]; } int main() { int T; cin >> T; while (T--) { int n; cin >> n >> m >> w2 >> w3; dp.clear(); cout << dfs(n) << endl; } return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.*; public class Main { static Map<Integer, Integer> dp; static int m, w2, w3; static int dfs(int i) { if (i >= m) return 0; if (dp.containsKey(i)) return dp.get(i); int cost2 = dfs(i * 2) + w2; int cost3 = dfs(i * 3) + w3; int res = Math.min(cost2, cost3); dp.put(i, res); return res; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int T = sc.nextInt(); while (T-- > 0) { int n = sc.nextInt(); m = sc.nextInt(); w2 = sc.nextInt(); w3 = sc.nextInt(); dp = new HashMap<>(); System.out.println(dfs(n)); } sc.close(); } }
Python:[此代码未进行大量数据的测试,仅供参考]
T = int(input()) for _ in range(T): n, m, w2, w3 = map(int, input().split()) dp = {} def dfs(i): if i >= m: return 0 if i in dp: return dp[i] dp[i] = min(dfs(i * 2) + w2, dfs(i * 3) + w3) return dp[i] print(dfs(n))
第二题
题目:漂亮数
我们定义一个漂亮数是这样的数:1、该数为正整数2、设该数为x,存在一个质数p使得x mod p = 0 且 p * p >= x给你一个正整数n,你能否求出有多少漂亮数小于等于n?
输入描述
输入一行一个正整数n(1< n< 5 * 10^6)。
输出描述
输出一行一个正整数,代表小于等于n的漂亮数的个数。
样例输入
10
样例输出
8
参考题解
筛质数基于最小质因数,递推计算每个数的最大质因数。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int n; cin >> n; vector<int> min_prime(n + 1, 0); // 最小质因数 vector<int> primes; // 欧拉筛法 for (int i = 2; i <= n; ++i) { if (min_prime[i] == 0) { min_prime[i] = i; primes.push_back(i); } for (int p : primes) { if (p > min_prime[i] || i * p > n) break; min_prime[i * p] = p; } } int count = 0; vector<int> max_prime(n + 1, 0); // 最大质因数 for (int x = 2; x <= n; ++x) { if (min_prime[x] == x) { max_prime[x] = x; count++; } else { int p = min_prime[x]; int m = x / p; max_prime[x] = max(p, max_prime[m]); if (1LL * max_prime[x] * max_prime[x] >= x) { count++; } } } cout << count << endl; return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] minPrime = new int[n + 1]; List<Integer> primes = new ArrayList<>(); // 欧拉筛法 for (int i = 2; i <= n; i++) { if (minPrime[i] == 0) { minPrime[i] = i; primes.add(i); } for (int p : primes) { if (p > minPrime[i] || i * p > n) break; minPrime[i * p] = p; } } int count = 0; int[] maxPrime = new int[n + 1]; for (int x = 2; x <= n; x++) { if (minPrime[x] == x) { maxPrime[x] = x; count++; } else { int p = minPrime[x]; int m = x / p; maxPrime[x] = Math.max(p, maxPrime[m]); if ((long) maxPrime[x] * maxPrime[x] >= x) { count++; } } } System.out.println(count); sc.close(); } }
Python:[此代码未进行大量数据的测试,仅供参考]
n = int(input()) max_n = n min_prime = [0] * (max_n + 1) # 最小质因数数组 primes = [] # 欧拉筛法预处理最小质因数 for i in range(2, max_n + 1): if min_prime[i] == 0: min_prime[i] = i primes.append(i) for p in primes: if p > min_prime[i] or i * p > max_n: break min_prime[i * p] = p count = 0 max_prime = [0] * (max_n + 1) # 最大质因数数组 for x in range(2, max_n + 1): if min_prime[x] == x: # x是质数 max_prime[x] = x count += 1 else: # x是合数 p = min_prime[x] m = x // p max_prime[x] = max(p, max_prime[m]) if max_prime[x] * max_prime[x] >= x: count += 1 print(count)
第三题
题目:最长路径
游游很喜欢树,这一天他在研究树上的路径,他遇到了一个难题,现在邀请你帮助他解决该问题。在一棵树上,两个点并不一定能确定一条链,但是可以找到一条经过这两个点最长的一条链。你有一棵 n 个点的树,树上每条边都有一个权值,定义一条简单路径的长度为这条简单路径上的边权和,对于给定的两个点 x, y,你需要回答在树上经过这两个点的最长简单路径是多少。【树上的路径】从节点 u 到节点 v 的简单路径定义为从节点 u 出发,以节点 v 为终点,随意在树上走,不经过重复的点和边走出来的序列。可以证明,在树上,任意两个节点间有且仅有一条简单路径。
输入描述
第一行两个数 n, m (1< n, m < 10^5)。
接下来
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南