• 2020牛客暑期多校训练营(第二场)Just Shuffle


    题目链接

    https://ac.nowcoder.com/acm/contest/5667/J

    题目大意

    给你一个置换 B , 要求找到置换 P 使得 $PA^{k}=B$ , 其中 A 为 P 的置换规则

    解题思路 

    置换是满足逆元关系的

    $P=PA^{k}A^{-k}=BA^{-k}$

    一个置换的某个位置的某个数在改变了一定次数后一定会变回它自己,即每个位置都属于某个环中 

    我们设某个环的大小为 len , 那么这个环中的数置换的次数为 k % len

    我们设 t = k % len , 那么根据 t * t^-1 = 1 , 我们只要让这个环中的每个数再改变 t^-1次

    就可以回到初始的位置 , 而 t^-1 即是 k 在 % len 下的逆元

    AC_Code

    #include<bits/stdc++.h>
    #define int long long
    #define ll long long 
    using namespace std;
    ll exgcd1(ll a,ll b,ll &x,ll &y){if(!b){x=1,y=0;return a;}ll t=exgcd1(b,a%b,y,x);y-=a/b*x;return t;}
    ll get_inv(ll a,ll mod){ll x,y;ll d=exgcd1(a,mod,x,y);return d==1?(x%mod+mod)%mod:-1;}
    const int N = 3e5 + 10;
    int a[N] , vis[N] , ans[N];
    vector<int>vec;
    signed main()
    {
        ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0);
        int n , k;
        cin >> n >> k ;
        for(int i = 1 ; i <= n ; i ++) cin >> a[i];
        for(int i = 1 ; i <= n ; i ++)
        {
            if(vis[i]) continue ;
            vec.clear();
            vec.push_back(i) , vis[i] = 1;
            int now = a[i];
            while(now != i)
            {
                vec.push_back(now) , vis[now] = 1;
                now = a[now];
            }
            int sz = vec.size() , ny = get_inv(k , sz);
            for(int j = 0 ; j < sz ; j ++) ans[vec[j]] = vec[(j + ny) % sz];
        }
        for(int i = 1 ; i <= n ; i ++) cout << ans[i] << " ";
        cout << '
    ';
        return 0;
    }
  • 相关阅读:
    第一篇博文
    重拾javascript系列-JS声明详解之var
    重拾Javascript系列
    AtCoder DP Contest 26题
    DP题
    一众数论
    字符编码
    C# DateTime类型和sqlserver DateTime精度不同
    vs2015中的数据库架构对比工具(New Schema Comparison)
    SqlServer常用语句
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13345864.html
Copyright © 2020-2023  润新知