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;
}