1. 程式人生 > >優化-T2078 HKE與他的小朋友

優化-T2078 HKE與他的小朋友

題目連結:https://www.luogu.org/problemnew/show/T2078
題目背景

HKE帶著nn個小朋友做遊戲

題目描述

現在有n個座位編號為11至nn,這些小朋友也編號11至nn。一開始所有小朋友都坐在相應的座位上。HKE的遊戲可用一個n的排列A(A_1,A_2\cdots _nA(A 1​ ,A 2​ ⋯A n​ )表示。一輪遊戲時,對於所有的1\leq i\leq n1≤i≤n,坐在位置ii上的小朋友坐到位置A_iA i​ 上。

現在遊戲進行了kk輪,HKE想知道遊戲結束後,位置1,2\cdots n1,2⋯n分別坐了幾號小朋友?

輸入輸出格式

輸入格式:
第一行n,kn,k。

第二行A_1,A_2\cdots A_nA 1​ ,A 2​ ⋯A n

輸出格式:
一行n個數表示位置1,2……n1,2……n上的小朋友的編號

輸入輸出樣例

輸入樣例#1: 複製
5 5
2 3 1 5 4
輸出樣例#1: 複製
2 3 1 5 4
輸入樣例#2: 複製
5 4
2 3 1 5 4
輸出樣例#2: 複製
3 1 2 4 5
說明

30%的資料,n\leq1000n≤1000,k\leq1000k≤1000
100%的資料,n\leq100000n≤100000,k\leq2^{31}-1k≤2
31
−1

一開始打了個30分程式碼如下:

#include<iostream>
#include <algorithm>
using namespace std;

int k,n,a[100010],b[100010],c[100010];

int main()
{
	cin>>n>>k;
	for (int i=1;i<=n;i++)
	{
		cin>>a[i];
		b[i]=i;
	}
	
	for (int i=1;i<=k;i++)
	{
		for (int j=1;j<=n;j++)
		{
			c[a[j]]=b[j];
		}
		for (int j=1;j<=n;j++)
		{
			b[j]=c[j];
			cout<<b[j]<<" ";
		}
		cout<<endl; 
	}
	
//	for (int j=1;j<=n;j++)
//	{
//			cout<<b[j]<<" ";
//	}
		
    return 0;
}

大神給了個AC程式碼如下,仰望大神啊。

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    int A[100001];
    int s[100001],t[100001];
    long long n,k;
	long long m,p,q,r;
      
    cin >> n >> k;
    
    for(long long i=1;i<=n;i++){
        cin >> A[i];
        s[i]=0;
    }
    
    for(long long i=1;i<=n;i++){
    	
		if(s[i]>0) continue;
    	
    	m=0;
    	p=i;
    	t[0]=i;
    	do{//計算單個數重複週期 
    		p=A[p];
    		m++;
			t[m]=p;
		}while(p!=i);
		q=k%m;
		p=i;
		do{//全環設定 
			r=t[q];
			s[r]=p;
			p=A[p];
			q++;
			q=q%m;
		}while(p!=i);

	}
    
    for(long long i=1;i<=n;i++){
        cout << s[i] << " ";
    }
    return 0;
}