• J Just Shuffle(序列跳转)


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

    题意:要求构造出序列P,让初始排列A={1,2,3,4....n}依照P序列跳转k次后得到给定排列。

    分析:简单分析可发现,若存在合法情况的话,跳转的过程肯定在若干个简单环上;

       我们可以简单模拟,设每个环大小为mi,在环中的每个数会达到跳转后的k%m步,我们可以用数组来模拟这一步,如果每一个环都能跑满大小为mi 的数组且不重复即存在方案(只需gcd(mi,k%m)==1)

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define MP make_pair
    typedef long long ll;
    const int mod=998244353;
    const int M=2e5+6;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18;
    int to[M],book[M],lin[M],ans[M];
    vector<int>tmp;
    int main(){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&to[i]);
        for(int i=1;i<=n;i++){
            if(!book[i]){
                tmp.clear();
                int nowi=i;
                tmp.pb(nowi);
                book[nowi]=1;
                while(!book[to[nowi]]){
                    nowi=to[nowi];
                    tmp.pb(nowi);
                    book[nowi]=1;
                }
                int m=tmp.size();///环大小
                if(m==1){
                    ans[tmp[0]]=tmp[0];
                    continue;
                }
                int x=k%m;///需要跳多少步才能到达
                if(__gcd(m,x)!=1)
                    return puts("-1"),0;
                nowi=0;
                for(auto v:tmp){
                    lin[nowi]=v;
                    nowi+=x;
                    nowi%=m;
                }
                for(int i=0;i<m;i++)
                    ans[lin[i]]=lin[(i+1)%m];
            }
        }
        for(int i=1;i<=n;i++)
            printf("%d ",ans[i]);
    }
    View Code
  • 相关阅读:
    667. Beautiful Arrangement II
    695. Max Area of Island
    485. Max Consecutive Ones
    coedforces #481Div(3)(ABCDEFG)
    躲藏
    车辆问题(贪心)
    最小化代价(优先队列)
    PUBG
    hdu 2647 Reward(拓扑排序+优先队列)
    HDU 3342 Legal or Not(判断环)
  • 原文地址:https://www.cnblogs.com/starve/p/13298859.html
Copyright © 2020-2023  润新知