首页 > 其他分享 >[AGC061A] Long Shuffle 题解

[AGC061A] Long Shuffle 题解

时间:2023-10-26 21:45:42浏览次数:36  
标签:std Shuffle dbinom 题解 AGC061A shuffle 2K 2i mathrm

题意

给定一个满足 \(A_i=i\) 的排列 \(A\),求对其进行一次 \(\mathrm{shuffle}(1,N)\) 操作后其第 \(K\) 项的值。其中 \(\mathrm{shuffle}(L,R)\) 的定义如下:

  • 若 \(R = L + 1\),那么交换 \(A_L\) 和 \(A_R\) 的值
  • 否则,依次执行 \(\mathrm{shuffle}(L,R-1)\), \(\mathrm{shuffle}(L+1,R)\)

(\(1 \le T \le 1000, 1 \le K \le N \le 10^{18}\))。

题解

通过计算出 \(N\) 较小时的情况我们可以发现若 \(N\) 为偶数,对于一对下标,在执行操作 \(\mathrm{shuffle}(1,n)\) 操作后,有 \(2i - 1, 2i\),有 \(A_{2i - 1} = 2i - 1, A_{2i} = 2i\) 或 \(A_{2i - 1} = 2i, A_{2i} = 2i - 1\) 成立。换句话说,就是在 \(N\) 为偶数时,只会交换一些相邻且互不相交的数对。

考虑使用归纳法证明,设 \(N = 2K\),当 \(K = 1\) 时命题成立,对于 \(K > 1\) 的情况,可以发现会依次执行如下操作:

  • \(\mathrm{shuffle}(1,2K-2)\)
  • \(\mathrm{shuffle}(2,2K-1)\)
  • \(\mathrm{shuffle}(2,2K-1)\)
  • \(\mathrm{shuffle}(3,2K)\)

可以发现中间两次 \(\mathrm{shuffle}(2,2K-1)\) 操作相互抵消,所以只会剩下两个操作区间长度为 \(N - 2\) 的子操作,故命题成立。

因此在 \(N = 2K\) 的情况下,只要计算出数对 \(2i - 1, 2i\) 被操作的次数即可计算出对应位置的值。可以发现在初始时区间长度为 \(2K\),至最后会缩减至 \(2\),每次缩减有两种方案:右移左边界和左移右边界,那么从 \(N = 2K\) 缩减至数对 \(2i - 1, 2i\) 共需要缩减 \(K - 1\) 次,只有恰好缩减 \(i - 1\) 次右边界才能使得最终操作的数对为 \(2i - 1, 2i\),可以计算出方案数为 \(\dbinom{K - 1}{i - 1}\)。由于交换只有两种状态,那么我们只需要计算出 \(\dbinom{K - 1}{i - 1} \bmod 2\) 即可。使用卢卡斯定理直接计算即可在 \(\mathcal{O}(\log N)\) 的时间内完成计算。但是存在如下结论:

\[\dbinom{n}{m} \equiv 1 \bmod 2 \Leftrightarrow n \operatorname{AND} m = m \]

其中 \(\operatorname{AND}\) 表示按位与操作。

证明可以考虑卢卡斯定理的过程,设二进制下 \(n\) 的每一位依次为 \(a_i\),\(m\) 的每一位依次为 \(b_i\),那么有

\[\dbinom{n}{m}\bmod 2 = \prod\limits_{i}\dbinom{a_i}{b_i} \]

那么 \(\dbinom{n}{m} \equiv 1 \bmod 2\) 的充要条件即为 \(\forall i, \dbinom{a_i}{b_i} = 1\),即 \(a_i \operatorname{AND} b_i = b_i\),即 \(n \operatorname{AND} m = m\)。

因此我们可以快速计算 \(\dbinom{K - 1}{i - 1} \bmod 2\) 的值,若 \(N\) 为奇数那么分别计算两次区间长度为偶数的情况即可。

Code

#include <bits/stdc++.h>

typedef long long valueType;

valueType query(valueType N, valueType K) {
    if (((N / 2 - 1) & ((K + 1) / 2 - 1)) == ((K + 1) / 2 - 1))
        return (K & 1) ? K + 1 : K - 1;
    else
        return K;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType T;

    std::cin >> T;

    for (int testcase = 0; testcase < T; ++testcase) {
        valueType N, K;

        std::cin >> N >> K;

        if (N & 1)
            std::cout << query(N - 1, query(N - 1, K - 1) + 1) << std::endl;
        else
            std::cout << query(N, K) << std::endl;
    }

    return 0;
}

标签:std,Shuffle,dbinom,题解,AGC061A,shuffle,2K,2i,mathrm
From: https://www.cnblogs.com/User-Unauthorized/p/solution-AGC061A.html

相关文章

  • P4678 [BalticOI 2005] Bus Trip 题解
    P4678[BalticOI2005]BusTrip题解(RE:题解再改造!!)贴码#include<bits/stdc++.h>#defineMAXN500010usingnamespacestd;//ifstreamis("trip.in",ios::in);//ofstreamos("trip.out",ios::out);//#definecinis//#definecoutosintn,m,p,t,tote......
  • [HDU 3483] A Very Simple Problem 题解
    题目描述快速求出下面式子的值:\[\left(\sum\limits_{k=1}^{N}k^{x}x^{k}\right)\bmodM\]其中\(1≤N,M≤2\times10^9\),并且\(1≤x≤50\)。题解(solution)对于该类题目,\(N\)很大,而\(x\)很小,考虑矩阵快速幂优化。对于每一个\(N\)的答案,我们用\(f(N)\)来......
  • P5537 【XR-3】系统设计 题解-哈希+线段树二分
    20231026P5537【XR-3】系统设计题解-哈希+线段树二分这个东西怎么会和哈希有关?!直接寄。Statement这个系统首先需要输入一棵\(n\)个点的有根树和一个长度为\(m\)的序列\(a\),接下来需要实现\(q\)个操作。操作分两种:1xlr表示设定起点为有根树的节点\(x\),接下来......
  • CF888E题解
    分析看到\(n\leq35\)的数据范围就想到了meet-in-middle。先爆搜出对于\(1\sim\frac{n}{2}\)和\(\frac{n}{2}\simn\)两个下标范围内在模意义下所有的和。然后用一个常见trick,就是枚举第二个部分的和,然后匹配第一个部分的和的最优解。显然匹配有两种情况,一种是......
  • chrome新版本http自动跳转https问题解决
    虽然是个好功能,但是部分内网业务还没做好https兼容,有的时候手工访问,还是变成https 解决办法:chrome://flags/找到:HTTPSUpgrades,修改disabled,重启解决,当然这个需要需要用户去调整,真正还需要服务去兼容https  ......
  • 在使用 Unity 2022 打包安卓项目时,遇到 gradle 无法访问或下载超级慢最终超时出错的问
    一般表现是打包最后一步会等待超长时间,最后报错,错误信息:PickedupJAVA_TOOL_OPTIONS:-Dfile.encoding=UTF-8FAILURE:Buildfailedwithanexception.*Whatwentwrong:Aproblemoccurredconfiguringrootproject'Gradle'.>Couldnotresolveallartifactsfor......
  • CCC 2023 题解 和 思考过程
    Trianglane水题,只要分情况判断中间和两侧有边叠牢的情况,每次减2#include<iostream>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>usingnamespacestd;typedeflonglongll;constintN=200010......
  • 「题解」Codeforces Round 905 (Div. 3)
    before终于有一篇题解是一次性更所有题的了。A.MorningProblemA.MorningSol&Code根据题意模拟即可。#include<bits/stdc++.h>typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT;int......
  • CF888C题解
    分析容易想到可以枚举每个字母,分别求其最小\(k\)取\(\min\)。思考对于一个\(k\),如何判其不合法。容易想到如果存在一个没有这个字符的长度大于等于\(k\)的子段,那么这个\(k\)就不合法。那么我们就知道如何求最小合法\(k\)了。找到最长的没有这个字符的子段,其长度加......
  • CF888A题解
    分析因为一个数不可能同时大于并小于它两边的数,所以两种数的集合不存在交集。所以分别扫一遍两种数的个数加在一起即可。代码#include<iostream>usingnamespacestd;constexprintMAXN(1000007);inta[MAXN];intn,ans;inlinevoidread(int&temp){cin>>t......