[CP / Codeforces] E. Vlad and an Odd Ordering(Div. 4)

E. Vlad and an Odd Ordering

image


我很喜欢这道题,第一是因为它对我来说很难,第二是因为它体现了数学中的一些美妙而神奇的性质。惭愧的是,初见时我并没能做出来,看了 editorial 后也似懂非懂,直到两个星期之后,才总算理清楚思路,并且给出了一种略微复杂的解法——不知道和官方题解是否重合。

题目大意是,你有标着 \(1\)\(n\)\(n\) 张卡片,现在你需要按如下顺序将它们依次摆放:

  • 首先从小到大摆放所有标着奇数的卡片;
  • 然后从小到大摆放所有标着奇数 \(\times{}2\) 的卡片;
  • 然后从小到大摆放所有标着奇数 \(\times{}3\) 的卡片;
  • ……
  • 直到所有卡片都被摆放完毕。

问第 \(k\) 张被摆放的卡片上面标的数字是什么(为方便,以下省略 “卡片” 一词)。

观察数据规模,如果暴力模拟的话必然会超时,所以需要研究其背后的规律。

定义第 \(i\) 轮摆放的数字等于 “奇数 \(\times{}i\)”,为了找到突破口,我先模拟了一下 \(n=12\) 时的情况:

  • 第 1 轮:\([1\ 3\ 5\ 7\ 9\ 11]\)
  • 第 2 轮:\([2\ 6\ 10]\)
  • 第 3 轮:\([]\)
  • 第 4 轮:\([4\ 12]\)
  • 第 5 轮:\([]\)
  • 第 6 轮:\([]\)
  • 第 7 轮:\([]\)
  • 第 8 轮:\([8]\)

注意到只有 \(2^{i-1}\) 轮时才有数字被摆放,这是巧合吗?下面展开分析。

首先,第一轮摆放的必定是所有的奇数,这意味着除 \(1\) 以外的奇数轮(比如第 \(3\)\(5\)\(7\) 轮)都不会摆放任何数字,因为奇数和奇数的乘积依然是奇数,而所有的奇数已在第一轮被摆放完了。

观察第 \(6\) 轮,它是偶数轮,但它同样没有摆放任何数字,因为 “奇数 \(\times{}6\)” 中,\(6=2\times{}3\),所以在这一轮将要摆放的数字在第 \(2\) 轮中已经出现过了。

更一般地,我们会发现,所有满足 \(i=2^w\cdot{}m\)\(m\) 为大于 \(1\) 的奇数,\(w\) 为正整数)的轮次都不会摆放任何数字,因为该轮次本应该摆放的数字早就在第 \(2^w\) 轮中出现过了。

因此得出结论,只有在轮次为 \(2^w\) 时才会摆放数字,所以我们可以统计每个这样的轮次摆放数字的总个数,逐个累加,直到找到 \(k\) 所处的轮次,且 \(k\)该轮次内 是第 \(j\) 个数,那么第 \(k\) 个被摆放的数字就等于 \(2^w\times{}(2j-1)\)

每个轮次摆放的数字总个数可以通过以下方法获得:

  • 计算 \(a=\lfloor{}\frac{n}{2^w}\rfloor{}\) 得到每一轮所乘的最大奇数
  • 如果 \(a\) 是偶数,则将其减一
  • 再通过 \(b=\lceil{}\frac{a}{2}\rceil{}\) 得到该轮所乘奇数的总个数,也即该轮摆放的数字个数

因此得到代码:

代码 1(\(O(logn)\)

void solve() {
    int n, k;
    std::cin >> n >> k;

    int cnt = 0, w = 1, t;
    while (1) {
        t = n / w;
        t -= !(t & 1);
        t = (t + 1) / 2;

        if (cnt + t >= k)
            break;

        cnt += t;
        w <<= 1;
    }

    std::cout << ((k - cnt) * 2 - 1) * w << '\n';
}

官方题解提供了两种做法:第一种和我的解法类似,第二种采用了更为简洁的递归,但原理和前面其实是相同的,代码附在下面。

代码 2(\(O(logn)\)

int dfs(int n, int k) {
    if (k <= (n + 1) / 2) {
        return k * 2 - 1;
    }
    return 2 * dfs(n / 2, k - (n + 1) / 2);
}

void solve() {
    int n, k, ans = 0;
    std::cin >> n >> k;

    std::cout << dfs(n, k) << '\n';
}
posted @ 2024-03-04 14:58  ZXPrism  阅读(47)  评论(0)    收藏  举报