描述
Jimmy老师的N头宠物吃饱后(1≤N≤100)站成了一排。对于每一个1≤i≤N,从左往右数第i头宠物的编号为i。他想到了一个新的晨练方案给这些宠物。他让她们重复以下包含两个步骤的过程K(1≤K≤109,109表示10的9次方)次:
当前从左往右数在位置A1…A2的宠物序列反转她们的顺序(1≤A1<A2≤N)。
然后,在当前从左往右数在位置B1…B2的宠物序列反转她们的顺序(1≤B1<B2≤N)。
当宠物们重复这一过程K次后,请对每一个1≤i≤N 输出从左往右数第i头宠物的编号。
输入描述
输入的第一行包含N和K。第二行包含A1和A2,第三行包含B1和B2。
输出描述
在第i行输出晨练结束时从左往右数第i头宠物的编号。
用例输入 1
7 2 2 5 3 7
用例输出 1
1 2 4 3 5 7 6
提示
【数据范围】
30%的数据:1≤K≤1000;
100%的数据:1≤K≤10^9;
【样例解释】
初始时,宠物们的顺序从左往右为 [1,2,3,4,5,6,7]。在这一过程的第一步过后,顺序变为 [1,5,4,3,2,6,7]。在这一过程的第二步过后,顺序变为 [1,5,7,6,2,3,4]。再重复这两个步骤各一次可以得到样例的输出。
方法1,暴力傻子都会做:
#include <bits/stdc++.h>
using namespace std;
int n,k,a1,a2,b1,b2,a[101];
int main()
{
cin>>n>>k>>a1>>a2>>b1>>b2;
for(int i=1;i<=n;i++)
{
a[i]=i;
}
for(int i=1;i<=k;i++)
{
int j;
for(j=a1;j<=(a2+a1)/2;j++)
{
int x=a[j];
a[j]=a[a1+a2-j];
a[a1+a2-j]=x;
}
for(j=b1;j<=(b2+b1)/2;j++)
{
int x=a[j];
a[j]=a[b1+b2-j];
a[b1+b2-j]=x;
}
}
for(int i=1;i<=n;i++) cout<<a[i]<<'\n';
}
时间复杂度:O(kn)。
此方法必然超时,要寻求优化的办法。
我们发现,这道题目其实是有规律的,它在经过数次操作后会变成之前的状态。假设在模拟Q次后重复,则只需要模拟K%Q此就足够了。
时间复杂度为:O(nQ)
方法2:
#include <bits/stdc++.h>
using namespace std;
int n,k,a1,a2,b1,b2,f[101];
int cz(int x)
{
if (a1<=x&&x<=a2) x=a1+a2-x;
if (b1<=x&&x<=b2) x=b1+b2-x;
return x;
}
int main()
{
cin>>n>>k>>a1>>a2>>b1>>b2;
for(int i=1;i<=n;++i)
{
int p=1,q=cz(i);
while(q!=i){
p++;
q=cz(q);
}
int g=k%p;
for (int j=0;j<g;++j) q=cz(q);
f[q]=i;
}
for(int i=1;i<=n;++i) cout<<f[i]<<'\n';
}
由于本人是小学生,讲解不足之处,敬请谅解。