2020寒假【gmoj2410】【 Swapity Swap】【类似快速幂】

题目描述

Farmer John 的 N 头奶牛(1≤N≤10^5)站成一排。对于每一个 1≤i≤N,从左往右数第 i 头奶牛的编号为 i。Farmer John 想到了一个新的奶牛晨练方案。他给奶牛们 M 对整数 (L1,R1)…(LM,RM),其中 1≤M≤100。他让她们重复以下包含 M 个步骤的过程 K(1≤K≤10^9)次:
对于从 1 到 M 的每一个步骤i:当前从左往右数在位置 Li…Ri 的奶牛序列反转她们的顺序。
当奶牛们重复这一过程 K 次后,请对每一个 1≤i≤N 输出从左往右数第 i 头奶牛的编号。

输入

输入的第一行包含 N, M 和 K。对于每一个 1≤i≤M,第 i+1 行包含 Li 和 Ri,均为范围在 1…N 内的整数,其中 Li<Ri。

输出

在第 i 行输出指令序列执行了 K 次后奶牛序列中从左往右数第 i 个元素的编号。

样例输入

7 2 2
2 5
3 7

样例输出

1
2
4
3
5
7
6

数据范围限制

测试点 1-2 满足 N=K=100。
测试点 3-5 满足 K≤10^3。
测试点 6-10 没有额外限制。

提示

初始时,奶牛们的顺序从左往右为 [1,2,3,4,5,6,7]。在这一过程的第一步过后,顺序变为 [1,5,4,3,2,6,7]。在这一过程的第二步过后,顺序变为 [1,5,7,6,2,3,4]。再重复这两个步骤各一次可以得到样例的输出。

分析

解题思路
对于初始的序列 1−N 我们可以把它看作数组的位置下标,那么每次操作不就是调换位置,不用管此时在这个位置上的数,也就是我们只要得出进行 M 次操作后第 i 位会换到的位置并标记,每一轮结束后就只用调位置就行了,不用再模拟一遍 M 。
本题的核心思想:把本次的序号转化为下一次的数
例:因为a[1]=2,所以b[1]=a[2]。a和b的下标相同,a数组的2变成a[2]。

上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k;
int a[35][100001];
/*本题的核心思想:把本次的序号转化为下一次的数
例:因为a[1]=2,所以b[1]=a[2]。a和b的下标相同,a数组的2变成a[2]*/ 
void change(int x,int y)
{
	for(register int i=1;i<=n;i++)
	{
		a[x][i]=a[y][a[x][i]];
	}
	return;
}
int main()
{
	freopen("swap.in","r",stdin);
	freopen("swap.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(register int i=1;i<=n;i++) 
    {
    	a[0][i]=a[1][i]=i;
	}
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		for(register int i=x;i<=(x+y)/2;i++)
		{
			swap(a[1][i],a[1][x+y-i]);
		}
	}
	for(register int i=2;i<=31;i++)
	{
		for(register int j=1;j<=n;j++)
		{
			a[i][j]=a[i-1][j];
		}
		change(i,i-1);
	}
	for(register int i=1;i<=n;i++)
	{
		a[32][i]=a[0][i];
	}
	int count=1;
	while(k!=0)
	{
		if(k%2!=0)
		{
			change(32,count);
		}
		count++;
		k=k/2;
	}
	for(int i=1;i<=n;i++)
	{
		printf("%d\n",a[32][i]);
	}
	fclose(stdin);
	fclose(stdout);
    return 0;
}

发布了110 篇原创文章 · 获赞 100 · 访问量 8002

猜你喜欢

转载自blog.csdn.net/dglyr/article/details/105676642