Codeforces Round 885 (Div. 2)D. Vika and Bonuses(数学)

发布时间 2023-08-30 10:29:35作者: XiCen

题目链接: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;
}

是一道比较纯的数学题了吧:)