原题链接:https://codeforces.com/contest/1650/problem/D
解题思路: 仔细审题,会发现对第i个数字做的操作不会影响到后面的i+1…等数字。即可以反过来从最后一步开始还原到初始状态,如最后一步(设为第i步),需要做的处理是让他回到最后的位置,通过输入时记录的数字所处的位置对i求余,即可得到他移动到最后位置(还原到第i-1步状态)所需的步数。再将纪录的状态变到第i-1步,再同上进行处理,最后到第一步,即可得到结果。
期间所走的步骤即是从头开始移动到最后输入状态的步骤。
以题目第一个例子为例:
最终输入状态:3 2 5 6 1 4
一: 记录所所处位置的s数组为{0,5 ,2,1,6,3,4}(即数字1处在5号位置…)
二: 按思路处理,先处理数字6(它应该是最晚移动的),其位置为S[6]=4
三: 对6(当前处理数字总数)求余,得移动步骤4;
四: 每个数字往左移四位。(即s[j]-4,注意当s[j]<1时需要+6校正)
五: 再对前五个数进行处理。方法类似。
ac代码:
#include<iostream>
using namespace std;
int num[2005], s[2005], st[2005];
int main()
{
int t;cin >> t;while (t--){
int n;cin >> n;for (int i = 1; i <= n; i++)//输入的同时记录最后每个数所排列的位置{
cin >> num[i];s[num[i]] = i;}for (int i = n; i > 0; i--){
int step = s[i] % i;//算出最后一个移动的步数st[i] = step;for (int j = 1; j <= n; j++)//还原到第i-1步{
s[j] -= step;if (s[j] < 1)s[j] += i;}}for (int i = 1; i <= n; i++)cout << st[i] << ' ';cout << endl;}return 0;
}