[lnsyoj2228]密码游戏

题意

给定序列 x,y,要求构造出序列 a,b,使得对于第 i 次操作,baxi=y,每次操作后,将 a 循环移位一次,若 a 变为原序列,则将 b 循环移位一次

赛时 0PTS

DFS 写挂了 awa

sol

对于 xiyi,可列出

b(a(xi+i)%m+im)%m=yi

我们取任意一对 yi=yj,得

b(a(xi+i)%m+im)%m=b(a(xj+j)%m+jm)%m

由于 b0m1 的排列,因此可得

a(xi+i)%m+ima(xj+j)%m+jm(modm)

移项,得

a(xi+i)%ma(xj+j)%mjmim(modm)

这是 aiajk(modm) 的形式,因此我们使用加权并查集维护。(下以 ai,aj,k 称呼)
可以将 aiaj 使用并查集连接起来,使 aj 成为 ai 的祖宗节点。为了确保最终的根为 0,从而使得 ai=valivali 为节点 i 在并查集中的权值),我们需要使更小的节点成为另一个节点的祖宗,因此,如果 aj>ai,需要在等式两边同时 ×1
在连接时,我们可将 ajai 的祖宗节点连接,此时,需使 ajai 的权值和为 k,因此,这条连接的边,权值应为 kvalai,即权值和减去从 aiai 祖宗节点的权值和。
在枚举时,可以使用一个 vector,将 y 值相同的 x 值及其下标记录在一起。在枚举时,只需枚举同一 vector 中相邻的两元素(想一想,为什么?),并进行连边即可

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define x first
#define y second

using namespace std;
typedef pair<int, int> PII;

const int N = 100005, M = 30;

int n, m;
int x[N], y[N];
int f[M], d[M];
int a[N], b[N];
vector<PII> g[M];

int find(int x){
    if (x == f[x]) return x;
    int fa = find(f[x]);
    d[x] = ((d[x] + d[f[x]]) % m + m) % m;
    return f[x] = fa;
}

int main(){
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i ++ ) f[i] = i;
    for (int i = 0; i < n; i ++ ) scanf("%d", &x[i]);
    for (int i = 0; i < n; i ++ ) scanf("%d", &y[i]), g[y[i]].push_back({x[i], i});

    for (int i = 0; i < m; i ++ )
        for (int j = 1; j < g[i].size(); j ++ ){
            int u = (g[i][j - 1].x + g[i][j - 1].y) % m, v = (g[i][j].x + g[i][j].y) % m, val = g[i][j].y / m - g[i][j - 1].y / m;
            if (u < v) swap(u, v), val *= -1;
            int fu = find(u), fv = find(v);
            if (fu == fv) continue;
            f[fu] = v;
            d[fu] = ((val - d[u]) % m + m) % m;
        }
    for (int i = 0; i < m; i ++ ) find(i), a[i] = d[i];

    for (int i = 0; i < n; i ++ ) b[(a[(x[i] + i % m) % m] + i / m) % m] = y[i];

    for (int i = 0; i < m; i ++ ) printf("%d ", a[i]);
    puts("");
    for (int i = 0; i < m; i ++ ) printf("%d ", b[i]);
    puts("");
}
posted @   是一只小蒟蒻呀  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示