怎么前三题都是思维题啊。
思路
总共有三个操作,先不看翻转操作。
如果你右移 \(x\) 位之后,左移 \(x\) 位,那么就相当于没有操作。这个应该是很好理解的。
我们根据上面的结论,能得出以下代码。
if(op==">"){
cin>>x;
f+=x;
}
else if(op=="<"){
cin>>x;
f-=x;
}
变量 \(f\) 是最终应该右移多少位,\(op\) 是操作,\(x\) 是位数。
统计出最终右移多少位,最后进行操作。
接着看翻转。
首先,翻转两次是可以抵消的。
思考,翻转前需要右移 \(x\) 位,那么翻转后需要右移多少位呢?
不妨举个例子。
如果字符串 abcde
需要右移 1 位。按正常顺序,先右移,变成 eabcd
,再翻转,变成 dcbae
。如果先翻转,变成 edcba
,发现只需要在左移 1 位,即右移 -1 位,就正好可以变为 dcbae
。
因此我们的规律是,翻转前需右移 \(x\) 位,翻转后需右移 \(-x\) 位。
仔细在脑子里想一想,画一画,发现这个规律很显然成立,主要是需要想到这一步。
然后这个问题就可以解决了。
如果是左移或右移,就按前面的操作办。如果是翻转,就看记录次数,并且变量 \(f\) 应该乘上 -1,最后如果总共翻转奇数次,则需要给字符串翻转,然后右移即可。
还有一下几点需要注意:
-
如果一个字符串右移自己的长度位,就相当于没有操作,所以最终需要将 \(f\) 对字符串长度取模。
-
最后取模的话,一定要开
long long
。
AC CODE
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
int T,f=0,x,n,fg=0;
string s;
cin>>s;
n=s.size();
cin>>T;
while(T--){
string op;
cin>>op;
if(op==">"){
cin>>x;
f+=x;
}
else if(op=="<"){
cin>>x;
f-=x;
}
else{
f=-1*f;
fg=(fg==0?1:0);
}
}
f=f%n;
if(fg)reverse(s.begin(),s.end());
if(f==0)return cout<<s,0;//这里应该不要这么麻烦
if(f>0){
cout<<s.substr(n-f)<<s.substr(0,n-f);
}
else{
f=abs(f);
cout<<s.substr(f)<<s.substr(0,f);
}
return 0;
}
标签:右移,题解,cin,long,P10058,fg,翻转,op
From: https://www.cnblogs.com/xdh2012/p/17966541