Codeforces Round #776 (Div. 3)-D. Twist the Permutation

原题链接: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值