Codeforces Round 885 (Div. 2)D. Vika and Bonuses(数学)
题目链接:https://codeforces.com/problemset/problem/1848/D
题意:
给定正整数s和k;
你需要维护一个计数器C,并且进行k次操作,每次操作是一下俩种之一:
1:C = C + s;
2:s = s + s % 10;
输出k次后C的最大值,一开始C = 0;
分析:
我们观察一次操作后,s的个位是多少;
0 --> 0 1-->1 2-->4 3-->6 4-->8 5-->0 6-->2 7-->4 8-->6 9-->8
可以看出,如果是0,那么不管操作多少次类型2 ,答案都不会有变化,故应该直接输出 s * k,同理,5也是;
我们可以看出,奇数操作一次后就会变成偶数,而偶数会在 2 4 8 6 这4个里面循环;
且循环后,s会增加20;
由此我们可以得出一个表达式:y =
这是一个二次函数,故可以套用公式,得出最大值是在
时取得,因为这个值不一定是整数,所以我们需要在他的向下取整和向上取整里选最大值;
需要注意的是,一方面要时刻取最大值,另一方面是注意x的取值范围;
时间复杂度:O(1)
代码:
#include<bits/stdc++.h> #define int long long int cul(int s, int k) { int ans = s * k; int x = std::max(std::min((5 * k - s) / 40, k / 4), 0ll); ans = std::max(ans, (s + 20 * x) * (k - 4 * x)); x = std::min(x + 1, k / 4); ans = std::max(ans, (s + 20 * x) * (k - 4 * x)); return ans; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int T; std::cin >> T; while (T--) { int s, k; std::cin >> s >> k; int ans = s * k; if (k == 0) { std::cout << ans << "\n"; continue; } if (s % 10 == 0) { std::cout << ans << "\n"; continue; } if (s % 10 == 5) { ans = std::max(ans, (s + 5) * (k - 1)); std::cout << ans << "\n"; continue; } int a = s % 10; if (a % 2 == 1)s += a, k--; for (int i = 1; i <= 4 && k; ++i) { ans = std::max(ans, cul(s, k)); s += (s % 10); k--; } std::cout << ans << "\n"; } return 0; }
是一道比较纯的数学题了吧:)