• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

RomanLin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【裴蜀定理】codeforces 2244 C. Stepan and Permutation

题目

https://codeforces.com/problemset/problem/2244/C

题意

输入 \(T(\leq 1e4)\) 表示 \(T\) 组数据。所有数据的 \(n\) 之和 \(\leq 2e5\)。
每组数据输入 \(n(1 \leq n \leq 2e5)\text{ }x \text{ } y(1 \leq x,y \leq n 且 x+y \leq n)\) 和 1~n 的排列 \(p\)。

你可以执行如下操作任意次:
选择两个下标 \(i\) 和 \(j\),满足 \(|i-j| = x\) 或者 \(|i-j| = y\),然后交换 \(p[i]\) 和 \(p[j]\)。

能否把 \(p\) 排成升序?输出 YES 或 NO。

进阶:做到 O(1) 空间。

题解

一个下标位置 \(i\) 的元素,假设它能通过任意次交换操作抵达的全部的下标位置即为全集 \(U\)。对于任意下标位置 \(j \in U\),都会满足什么性质呢?

这里先给出结论:下标位置 \(i\) 的元素能够抵达的任意下标位置 \(j \in U\) 都满足 \(\text{i % gcd(x, y) == j % gcd(x, y)}\)

设 \(g=gcd(x,y)\),根据裴蜀定理,有:$$ax+by=cg$$
那么下标位置 \(i\) 的元素,就一定可以通过某种移动方案,达到任意一个在全集 \(U\) 的位置。

假设全部元素划分后,共有 \(U_1,U_2,...,U_k\) 共计 \(k\) 个彼此不相交的集合。对于同属于一个集合 \(U\) 的元素,一定是可以随意交换的。为什么同一连通块中的元素可以随意交换?详情见博客:https://zhuanlan.zhihu.com/p/2027293665970721660

那么我们只需要关注在 \(U_1,U_2,...,U_K\) 分别排序以后,是否可以使得原序列变成一个单调序列即可。此题有个额外的性质,就是原序列是一个排列,那么结合分组排序的性质,那么在排序前必须满足 \(i \equiv p[i](mod \text{ } g)\)。

参考代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);cin.tie(nullptr);
    int T;
    cin >> T;
    while (T--) {
        int n, x, y;
        cin >> n >> x >> y;
        int g = gcd(x, y);
        bool ok = true;
        for (int i = 1; i <= n; i++) {
            int v;
            cin >> v;
            if (v % g != i % g) {
                ok = false;
            }
        }
        if (ok) {
            cout << "YES\n";
        } else {
            cout << "NO\n";
        }
    }
    return 0;
}

posted on 2026-09-06 20:31  RomanLin  阅读(6)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3