题目描述
赞歌字符串是一个由 1,4,51,4,5 组成的字符串。每次操作 LsWn 会拿出左端点为 l,右端点为 r 的子串,(注意,第一个字符的下标为 11,最后一个字符的下标为 n)并把它替换为新的给出的子串。替换之后,你需要回答 33 个对于完整串的问询,分别是:
- 11 的个数。
- 整个字符串每个数位的总和。
- 整个字符串每个数位的乘积。
所有输出都要对 9982435399824353 取模。
输入格式
第一行一个字符串。
第二行一个数字 m 代表有 m 次操作
后面 m 行每行两个数字l,r,然后一个长 +1r−l+1 的字符串代表把 (l,r) 子串改为这个字符串。
输出格式
m 行,每行 33 个数,代表每次修改后的 33 个问询。
输入输出样例
输入 #1复制
114514 3 1 3 111 3 4 44 4 4 5
输出 #1复制
4 13 20 3 15 64 3 16 80
说明/提示
样例一的解释:
第一次操作,字符串变为 111514
,其中 11 的个数为 44,和为 1+1+1+5+1+4=131+1+1+5+1+4=13,乘积为 1×1×1×1×5×1×4=201×1×1×1×5×1×4=20。
第二次操作,字符串变为 114414
。
第三次操作,字符串变为 114514
。
我们设初始字符串长度为n。
对于 10%10% 的数据,n≤10。
对于 40%40% 的数据,n≤1000。
对于全部数据,n≤106,m≤103,1≤r−l+1≤103。
update:出题人心血来潮,在 2021/02/08 把时间压到了 100 ms,为 std 用时的 6 倍左右。
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e6 + 10, mod = 99824353;
char str[N], str1[N];
long long l, r, m;
long long a1[20], a4[N], a5[N];
int main()
{
cin >> str + 1 >> m;
for (int i = 1; str[i]; i++)
a1[str[i] - '0']++;
a4[0] = 1, a5[0] = 1;
for (int i = 1; i < N; i++)
{
//预处理4,5的次幂
a4[i] = (a4[i - 1] * 4)%mod;
a5[i] = (a5[i - 1] * 5)%mod;
}
while (m--)
{
long long a = 0, b = 1, k = 1;
cin >> l >> r >> str1;
for (int i = l; i<=r; i++)
{
a1[str[i] - '0']--;
a1[str1[i-l] - '0']++;
str[i] = str1[i - l];
}
cout << a1[1]<< " " << (a1[1] + a1[4] * 4 + a1[5] * 5) % mod << " " << (a4[a1[4]] * a5[a1[5]]) % mod << endl;
}
return 0;
}
预处理次幂,又学到了。。。。。