2020 Niuke Duo School 2 J Just Shuffle (Number Theory)

The meaning of the question: ask which permutation can be performed k times to turn 123...n into a given sequence. If there is no such permutation, output -1, where k is a prime number.

Analysis: According to the nature of permutation, permutation is composed of rings. Since k is a prime number, no matter what the period m of the ring is, m and k%m are mutually prime, so there must be a permutation that meets the requirements, so by number theory Knowledge must be able to find a b such that b*(k%m)==1(mod m), so that the given sequence can be multiplied by b times, and a permutation that meets the requirements is obtained. The specific permutation logic is compared I'm still very confused after watching it for a long time. It's better to write about replacement afterwards.

Code:

#include <bits/stdc++.h>
#define x first
#define y second
#define mid (l+r>>1)
#define lo (o<<1)
#define ro (o<<1|1)
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
typedef vector<int>vi;
struct tri{int x,y,z;};
const int inf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+10;
const ll mod=1e9+7;
const double PI=acos(0)*2;

int n,m,k,arr[N],v[N];
bool vis[N];
void f()
{
    if(m==1)return;

    ll a=k%m,b=1;
    for(;a*b%m!=1;b++);

    for(int i=0;i<m;i++)
        arr[v[i]]=v[(i+b)%m];
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
//    freopen("in.txt","r",stdin);
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>arr[i];
    for(int i=1;i<=n;i++)if(!vis[i])
    {
        m=0;
        for(int j=i;;)
        {
            vis[j]=1;
            v[m++]=j;//由于求的是环,这里j或者arr[j]一样
            j=arr[j];
            if(j==i)break;
        }//这一操作实际上是求出置换这条链的逆过程
        f();
    }
    for(int i=1;i<=n;i++)
        cout<<arr[i]<<' ';
    return 0;
}
/*
 *样例置换:2 3 1
 *等价于:
 *1->3
 *2->1
 *3->2
 *求出的数组v:1 2 3(变化为1->3->2->1->...)
 */

 

Guess you like

Origin blog.csdn.net/qq_43700916/article/details/108643759