P10058题解

怎么前三题都是思维题啊。

思路

总共有三个操作,先不看翻转操作。

如果你右移 \(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;
}
posted @ 2024-01-15 22:20  Xu_dh  阅读(31)  评论(0)    收藏  举报