C. Cut and Paste
题目链接:codeforces 1281C
题意:
题目较长,举例说明,T组样例,X次操作,给一个只包含‘1’‘2’‘3’的字符串s,在对s进行x次操作后,问s最终长度
举例:x = 5 ,s = 231
第一次操作: 将字符串分为两个分别是 2 和 31, 然后将31复制2次(复制2次是因为第一个字符是2),放在分开的第一个字符串2后面,拼成新的字符串2 31 31(中间本身没有空格,方便观察)
第二次操作:将第一次操作得到的字符串分为两个分别是 23 和131,然后将131复制3次(复制3次是因为第二个字符是3),放在分开第一个字符串23后面,形成新的字符串23 131 131 131
第三次操作:将第二次操作得到的字符串分为两个分别是 231 和 31131131,然后将 31131131复制1次(复制1次是因为第三个字符是1),放在分开的第一个字符串231后面,形成新的字符串231 31131131
.........依次类推,
分开的两个字符串,第一个字符串长度每次递增1
解题思路:
首先不能直接构造最终的字符串,会直接爆掉(超出内存),仔细分析后得出:只需构造出长度最长为x的字符串即可。
理由:得到第 i 个字符为多少即可知道后面的字符串复制了多少次,知道了字符串长度即可知道复制的字符串长度。
我感觉讲的差不多了,还是有问题的话,可以评论(有问题请多多指教)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
ll ans;
int main(){
int t;
cin >> t;
while(t--){
int x, l = 1;
string s;
cin >> x >> s;
int len = s.size();
while(len < x){
for(int i = 1; i < s[l-1] - '0'; i++){
s += s.substr(l, len -l); // 将分开的第二个字符串复制s[l-1]次后拼接
}
len = s.size();
l++;
}
// 此处的得到长度大于x的字符串
ans = s.size() % mod;
for(int i = l; i <= x; i++){ // 此处l指的是之前已经进行了多少次操作
ans = (ans + (s[i-1]-'0' - 1) * (ans - i) % mod + mod) % mod;
// s[i-1]-'0'指的是当前字符为几,-1是因为要少复制一次,如果是2本质上只用复制1次
// ans-i 是因为分开的两个字符串,第一个字符串每次递增1,那么ans-i就是需要复制的字符串长度
}
cout << ans << endl;
}
return 0;
}