Codeforces 1281 C
题目大致解释
T组样例,X次操作,给一个只包含‘1’‘2’‘3’的字符串s,在对s进行x次操作后,问s最终长度。
(模拟题)
举例:
s=123abc ; x=5
分开的两个字符串,第一个字符串长度每次递增1
第一次操作: 将字符串分为两个分别是 2 和 31, 然后将31复制2次(复制2次是因为第一个字符是2),放在分开的第一个字符串2后面,拼成新的字符串2 31 31
第二次操作:将第一次操作得到的字符串分为两个分别是 23 和131,然后将131复制3次(同上),放在分开第一个字符串23后面,形成新的字符串23 131 131 131
第三次操作:将第二次操作得到的字符串分为两个分别是 231 和 31131131,然后将 31131131复制1次(同上),形成新的字符串231 31131131(复制一次还是其本身)
…
思路:不能直接构造最后形成得字符串,,会容易超出内存,所以只需构造长度最长为x得字符串。当得到第i个字符是多少时,就可以知道后面字符中复制了几次,知道了字符串长度就可以知道复制的字符串长度。
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cstdio>
#include <list>
#include <deque>
#include <set>
#include <vector>
#include <map>
#include <cstring>
#include <iomanip>
#define max(a,b) (a>b?a:b)
#define ll long long
#define pi 3.141592653589793
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+100;
int main() {
int t;
ll m=0;
cin >> t;
while(t--) {
int x, l=1;
string s;
cin >> x>> s;
int len = s.length();
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的字符串
m= s.size() % mod;
for(int i = l; i <= x; i++) { //l指的是前面已经进行得操作数
m = (m + (s[i-1]-'0' - 1) * (m - i) % mod + mod) % mod;
}
// s[i-1]-'0'判断当前字符是多少,-1是指要少复制一次,例如当是2时实际上只用复制1次,是1时就是不进行复制,即其本身
// m-i 是因为要对字符串进行分割后再复制,分割后的第一个字符串每次递增1,那么m-i就是需要复制的字符串长度
cout << m << endl;
}
return 0;
}
拓展
substr函数
substr(pos,n)
返回一个string,包含s中从pos开始的几个字符的拷贝
其中pos默认值为0,n的默认值为s.size()-pos。
举例:s=123abc
-
不加参数会拷贝整个s。 s.substr()返回123abc
-
只有pos,从pos开始拷贝剩下的全部字符。 s.substr() 返回abc。
-
当pos超过字符串长度,会出现out_of_range的异常。
-
当pos+n超过时,则substr会调整n的值,只拷贝到string的末尾。