蚂蚁金服笔试 蚂蚁金服笔试题 0828
笔试时间:2024年08月28日 秋招
历史笔试传送门:2023秋招笔试合集
第一题
题目
小苯看中了一件价值为p元的物品,他手里有1个“打折券"和1个“立减券”。两种优惠券可以都用在物品上,且使用顺序也是任意的。两种优惠券分别以整数x和y的方式给出。打折券:如果当前物品价格为p,使用后,物品价格变为:x·p/100上取整。立减券:如果当前物品价格为P,使用后,物品价格变为:max(0,p-y)。即物品价格立减y元,但最多减到0.小苯想知道,这件价值为p的物品最少可以花多少钱买到。
输入描述
输入包含一行三个正整数p,x,y(1≤p≤10^9,1≤x≤100,1≤y≤10^9),分别表示物品的价格,“打折券”和“立减券”的优惠力度。
输出描述
输出包含一行一个整数,表示最少花费。
样例输入
4 70 1
样例输出
2
说明
可以先使用打折券,价格变为4*70/100=3(向上取整),再使用立减券,价格减为2。
参考题解
要找到小苯最少能花多少钱购买这件价值为p元的物品,我们需要考虑不同的使用优惠券的顺序,并计算每种情况下的最终价格。根据描述,有两种顺序:先使用“打折券”,再使用“立减券”。先使用“立减券”,再使用“打折券”。分别计算这两种情况的结果,然后取最小值即可。先使用打折券:打折后的价格为:p1 = ceil(x * p / 100)。这里的ceil表示向上取整。再使用立减券:final_price1 = max(0, p1 - y)。先使用立减券:立减后的价格为:p2 = max(0, p - y)。再使用打折券:final_price2 = ceil(x * p2 / 100)。比较两种情况的结果:最少花费为min(final_price1, final_price2)。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <cmath> using namespace std; int main() { long long p, x, y; cin >> p >> x >> y; // 情况1: 先打折再立减 long long p1 = (x * p + 99) / 100; // 相当于ceil(x * p / 100) long long final_price1 = max(0LL, p1 - y); // 情况2: 先立减再打折 long long p2 = max(0LL, p - y); long long final_price2 = (x * p2 + 99) / 100; // 相当于ceil(x * p2 / 100) // 输出最少花费 cout << min(final_price1, final_price2) << endl; return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); long p = scanner.nextLong(); long x = scanner.nextLong(); long y = scanner.nextLong(); // 情况1: 先打折再立减 long p1 = (x * p + 99) / 100; // 相当于ceil(x * p / 100) long finalPrice1 = Math.max(0, p1 - y); // 情况2: 先立减再打折 long p2 = Math.max(0, p - y); long finalPrice2 = (x * p2 + 99) / 100; // 相当于ceil(x * p2 / 100) // 输出最少花费 System.out.println(Math.min(finalPrice1, finalPrice2)); scanner.close(); } }
Python:[此代码未进行大量数据的测试,仅供参考]
import math # 输入 p, x, y = map(int, input().split()) # 情况1: 先打折再立减 p1 = (x * p + 99) // 100 # 相当于ceil(x * p / 100) final_price1 = max(0, p1 - y) # 情况2: 先立减再打折 p2 = max(0, p - y) final_price2 = (x * p2 + 99) // 100 # 相当于ceil(x * p2 / 100) # 输出最少花费 print(min(final_price1, final_price2))
第二题
题目
小红拿到了一个数组,她可以进行最多一次操作:选择一个元素,使其加1. 小红希望操作结束后,数组所有元素乘积的末尾有尽可能多的0。你能帮帮她吗?
输入描述
第一行输入一个正整数n,代表数组的大小。
第二行输入n个正整数ai,代表数组的元素。
1≤n≤10^5 1≤ai≤10^9
输出描述
一个整数,代表操作结束后,所有元素乘积的末尾0的数量最大值。
样例输入
4 1 2 3 4
样例输出
1
说明
将第四个元素加1即可,数组变成4,1,2,3,5,所有元素乘积为30,末尾有一个0。
参考题解
计算当前数组所有元素乘积的末尾0的数量,即统计数组中所有元素的因子2和因子5的总数,末尾0的数量就是这两个总数的最小值。对于每个元素ai,我们假设对其加1,计算其对总因子2和因子5数量的影响,并得出操作后的末尾0的数量。选择能够使末尾0数量最多的元素进行加1操作,并输出结果。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <vector> using namespace std; // 计算一个数中包含的因子f(2或5)的数量 int factCnt(int x, int f) { int count = 0; while (x % f == 0) { count++; x /= f; } return count; } int main() { int n; cin >> n; vector<int> a(n); int total2 = 0, total5 = 0; // 计算当前数组中所有元素的因子2和因子5的总数量 for (int i = 0; i < n; ++i) { cin >> a[i]; total2 += factCnt(a[i], 2); total5 += factCnt(a[i], 5); } int max0 = min(total2, total5); // 当前末尾0的数量 // 尝试对每个元素加1并计算新的末尾0数量 for (int i = 0; i < n; ++i) { int cur2 = factCnt(a[i], 2); int cur5 = factCnt(a[i], 5); int new2 = factCnt(a[i] + 1, 2); int new5 = factCnt(a[i] + 1, 5); // 更新因子2和因子5的数量 int new2 = total2 - cur2 + new2; int new5 = total5 - cur5 + new5; // 计算新的末尾0的数量 int new0 = min(new2, new5); max0 = max(max0, new0); } // 输出最大末尾0的数量 cout << max0 << endl; return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.Scanner; public class Main { // 计算一个数中包含的因子f(2或5)的数量 public static int factCnt(int x, int f) { int count = 0; while (x % f == 0) { count++; x /= f; } return count; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int[] a = new int[n]; int total2 = 0, total5 = 0; // 计算当前数组中所有元素的因子2和因子5的总数量 for (int i = 0; i < n; ++i) { a[i] = scanner.nextInt(); total2 += factCnt(a[i], 2); total5 += factCnt(a[i], 5); } int max0 = Math.min(total2, total5); // 当前末尾0的数量 // 尝试对每个元素加1并计算新的末尾0数量 for (int i = 0; i < n; ++i) { int cur2 = factCnt(a[i], 2); int cur5 = factCnt(a[i], 5); int new2 = factCnt(a[i
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
持续收录字节、腾讯、阿里、美团、美团、拼多多、华为等笔试题解,包含python、C++、Java多种语言版本,持续更新中。