CodeForces 1345 B Card Constructions 二分查找

1. 題目描述

1.1. Limit

Time Limit: 1000 ms

Memory Limit: 256 MB

1.2. Problem Description

A card pyramid of height 11 is constructed by resting two cards against each other. For (h>1)(h >1), a card pyramid of height hh is constructed by placing a card pyramid of height h1h - 1 onto a base.A base consists of hh pyramids of height 11, and h1h - 1 cards on top. For example, card pyramids of heights 11, 22, and 33 look as follows:

1

You start with nn cards and build the tallest pyramid that you can. If there are some cards remaining, you build the tallest pyramid possible with the remaining cards. You repeat this process until it is impossible to build another pyramid. In the end, how many pyramids will you have constructed?


1.3. Input

Each test consists of multiple test cases. The first line contains a single integer t(t1000)t( \le t \le 1000) — the number of test cases. Next tt lines contain descriptions of test cases.

Each test case contains a single integer n(1n109)n(1 \le n \le 10^9) — the number of cards.

It is guaranteed that the sum of nn over all test cases does not exceed 10910^9.


1.4. Output

For each test case output a single integer — the number of pyramids you will have constructed in the end.


1.5. Sample Input

5
3
14
15
24
1

1.6. Sample Output

1
2
1
3
0

1.7. Note

In the first test, you construct a pyramid of height 1 with 2 cards. There is 1 card remaining, which is not enough to build a pyramid.

In the second test, you build two pyramids, each of height 2, with no cards remaining.

In the third test, you build one pyramid of height 3, with no cards remaining.

In the fourth test, you build one pyramid of height 3 with 9 cards remaining. Then you build a pyramid of height 2 with 2 cards remaining. Then you build a final pyramid of height 1 with no cards remaining.

In the fifth test, one card is not enough to build any pyramids.

1.8. Source

CodeForces 1345 B Card Constructions


2. 解讀

通過遞推方程 f(x)=f(x1)+3x1f(x) = f(x-1) + 3x - 1 推導構建 xx 層金字塔需要多少張卡牌。計算出來以後存儲在 listlist 中,10910^9 內最多 25820 層卡牌金字塔,計算到這裏即可。

然後對每個輸入 mm,對 listlist 進行循環二分查找,找到 list[x]m<list[x+1]list[x] \le m < list[x+1],然後 m=mlist[x]m = m - list[x],直到 m<2m<2,不再能搭建金字塔。輸出循環二分查找的次數 ansans,即最多能搭建多少金字塔。

3. 代碼

#include <iostream>
#include <map>
#include <math.h>
#include <string.h>
using namespace std;

// 10^9 內最多 25820 層卡牌金字塔
const int NUM = 25821;

// 存儲
int list[NUM];
// 存儲結果
int ans;
// 存儲
map<int, int> mp;
// 計算
void claculate(int m)
{
    list[1] = 2;
    for (int i = 2; i <= m; i++) {
        // 遞推方程
        list[i] = list[i - 1] + 3 * i - 1;
    }
}

// 二分查找
int binary_search(int array[], int low, int high, int target)
{
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (array[mid] <= target && array[mid + 1] > target) {
            return mid;
        } else if (array[mid] > target) {
            high = mid - 1;
        } else if (array[mid] < target) {
            low = mid + 1;
        }
    }
    return -1;
}

int main()
{
    // test case
    int t;
    scanf("%d", &t);
    // 卡片數量
    int m, buffer;
    // 初始化
    memset(list, 0, sizeof(list));
    // 計算
    claculate(NUM - 1);
    // test case
    for (int i = 0; i < t; i++) {
        ans = 0;
        // 卡片數量
        scanf("%d", &m);
        buffer = m;
        if (mp.find(m) == mp.end()) {
            // 查找
            while (buffer >= 2) {
                buffer -= list[binary_search(list, 0, (NUM - 1), buffer)];
                ans++;
            }
            // 存儲結果
            mp[m] = ans;
        } else {
            ans = mp[m];
        }
        // 輸出
        printf("%d\n", ans);
    }
}

聯繫郵箱:[email protected]

Github:https://github.com/CurrenWong

歡迎轉載/Star/Fork,有問題歡迎通過郵箱交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章