AcWing 4741. 魔法百合井

130 阅读2分钟

AcWing 4741. 魔法百合井

森林里有一口很深的魔法井,井中有 L 朵百合花。

你带着一个大空篮子和足够多的硬币来到了井边。

这个井有魔力,向里面投入硬币可以发生神奇的事情:

  • 如果你向井里一次性投入 1 个硬币,井就会发动魔法,将一朵百合花扔进你的篮子里。
  • 如果你向井里一次性投入 4 个硬币,井就会发动魔法,统计并记录到目前为止,已经扔进你的篮子里的百合花的数量。
  • 如果你向井里一次性投入 2 个硬币,井就会发动魔法,将等同于上次记录数量的百合花扔进你的篮子里。

有一点需要特别注意,如果你向井里一次性投入 1 个或 2 个硬币后,井中已经没有足够的百合花扔给你了,那么井就不会发动任何魔法,也不会扔给你任何百合花(钱白花了)。

请你计算,为了将所有百合花都收入篮中,所需要花费的最少硬币数量。

输入格式

第一行包含整数 T,表示共有 T 组测试数据。

每组数据占一行,包含一个整数 L,表示井中百合花的总数量。

输出格式

每组数据输出一个结果,每个结果占一行。

结果表示为 Case #x: y,其中 x 为组别编号(从 11 开始),y 为需要花费的最少硬币数量。

数据范围

1≤T≤100,
1≤L≤10510^5

输入样例:

2
5
20

输出样例:

Case #1: 5
Case #2: 15

样例解释

对于 Case 1,井中一共有 55 朵百合花。

最佳方案是一个接一个的连续向井中投入 55 个硬币,这样我们可以一个接一个的得到 55 朵百合花。

一共需要花费 55 个硬币。

对于 Case 2,井中一共有 1515 朵百合花。

最佳方案为:

  • 首先,一个接一个的连续向井中投入 55 个硬币,这样我们可以一个接一个的得到 55 朵百合花。
  • 然后,我们一次性向井中投入 44 个硬币,这样井会记录下到目前为止扔进我们篮中的百合花数量为 55。
  • 最后,我们重复三次,每次向井中投入 22 个硬币,这样每次都可以得到 55 朵百合花,从而得到剩余的全部 1515 朵百合花。

一共需要花费 1515 个硬币。

ac代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int dp[N];

int main () {
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;

    for (int i = 1; i < N; i ++) {
        dp[i] = min(dp[i], dp[i-1] + 1);
        for (int j = i + i, k = 1; j < N; j += i, k ++) {
            dp[j] = min(dp[j], dp[i] + 4 + 2 * k);
        }
    }

    int T; cin >> T;
    for (int t = 1; t <= T; t++) {
        int n; cin >> n;
        cout << "Case #" << t << ": " << dp[n] << endl;
    }
    return 0;
}