传送门:洛谷 Vlad and an Odd Ordering | Codeforces E. Vlad and an Odd Ordering

更佳的阅读体验:CF1926E 题解


简要题意:有 $n$ 张牌,按照编号为奇数、二倍奇数、三倍奇数、四倍奇数……的顺序出牌,直到出完所有的牌。求出的第 $k$ 张牌是什么。

手模一下样例中 $n = 7$ 的情况,不难发现,我们令第 $i$ 轮出牌数量后剩下 $m_i$ 张牌,则可以得到第一轮出牌 $\left \lceil \tfrac{n}{2} \right \rceil$ 张,$m_1 = \left \lfloor \tfrac{n}{2} \right \rfloor$ ,第二轮出牌 $\left \lceil \tfrac{m_1}{2} \right \rceil$ 张,$m_2 = \left \lfloor \tfrac{m_1}{2} \right \rfloor$,以此类推。

因此,我们只需要一轮一轮地出牌,并给 $k$ 减去这一轮出牌的数量,直到 $k$ 不大于当前剩余的牌数。

出牌次数这一轮的牌的编号牌编号之间的差
第 $1$ 次出牌$1$、$3$、$5$、$7$$2$
第 $2$ 次出牌$2$、$6$$4$
第 $3$ 次出牌$4$

可以发现,第 $i$ 轮出的牌编号的差为 $2^i$,这一轮出的第一张牌的编号是 $2^{i - 1}$,因此在经过上面的处理后就可以得到第 $k$ 张牌了。

#include <iostream>
using namespace std;
using ll = long long;

int t;
ll n, k;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    for (cin >> t; t; --t) {
        cin >> n >> k;
        ll cnt = 1, tmp = n;
        while (k > (tmp + 1) >> 1) {
            k -= tmp + 1 >> 1;
            tmp >>= 1, cnt <<= 1;
        } cout << (k * cnt << 1) - cnt << '\n';
    } return 0;
}
最后修改:2024 年 02 月 23 日
如果觉得我的文章对你有用,请随意赞赏