LuoguP6553 Strings of Monody 題解
阿新 • • 發佈:2021-12-21
LuoguP6553 Strings of Monody 題解
(至於第三個答案為什麼不需要乘 \(1^{ans_1}\) 大家應該都弄得明白,在此不再贅述)。
Content
給定一個長度為 \(n\) 的字串 \(s\)(僅包含 \(1,4,5\) 三種字元,\(n\) 在本題中無需輸入),有 \(m\) 個操作,每次操作給定兩個整數 \(l,r\),再給定一個字串 \(s'\),將 \(s\) 的從 \(l\) 到 \(r\) 的子串換成 \(s'\)。請在每次操作後求出:
- 字串中 \(1\) 的個數。
- 字串中所有數的總和。
- 字串中所有數的乘積。
以上資料都要對 \(9982\color{red}\text{43}\color{black}\text{53}\) 取模(注意!不是 \(998244353\))。
資料範圍:\(n\leqslant 10^6,m\leqslant 10^3,1\leqslant r-l+1\leqslant 10^3\) 。
Solution
這道題目看上去比較麻煩,其實只需要暴力模擬就可以搞定。
首先,我們可以看到,每次的變換範圍不會超過 \(10^3\),所以,我們可以考慮一種 \(\mathcal{O}(m(r-l+1))\) 的演算法——每次只考慮變換要變換的子串,然後更新要求的三個問題的答案。
我們可以開一個計數器 \(ans_1,ans_4,ans_5\)(\(ans_i\) 表示 \(i\) 在字串中出現的次數),每次操作就要更新著三個計數器的值,那麼三個問題的答案就是 \(ans_1,ans_1+4\times ans_4+5\times ans_5,4^{ans_4}\times5^{ans_5}\)
這裡冪次方取模明擺著用快速冪輕鬆搞定。
最後一點坑的就是:注意模數,不是 \(998244353\),這裡應該是 \(99824353\),少了一個 \(4\)!
總體來說難度不算太大,但要考慮的細節卻不少。
Code
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> using namespace std; typedef long long ll; ll quickpow(ll a, ll b, ll p) { if(p == 1) return 0; ll res = 1; b %= p; for(; b; b >>= 1) { if(b & 1) res = res * a % p; a = a * a % p; } return res; } ll n, m, sum1, sum, mul = 1, aa[17]; char s[1000007]; void test1() { printf("%lld %lld %lld\n", aa[1], aa[4], aa[5]); } int main() { scanf("%s%d", s + 1, &m); n = strlen(s + 1); for(int i = 1; i <= n; ++i) aa[s[i] - '0']++; // test1(); while(m--) { char tmp[1007]; int xx, yy; scanf("%d%d%s", &xx, &yy, tmp + 1); for(int i = 1; i <= yy - xx + 1; ++i) { // printf("%c %c\n", s[xx + i - 1], tmp[i]); aa[s[xx + i - 1] - '0']--; aa[tmp[i] - '0']++; s[xx + i - 1] = tmp[i]; } // test1(); printf("%lld %lld %lld\n", aa[1], (aa[1] + aa[4] * 4 + aa[5] * 5) % 99824353, (quickpow(4, aa[4], 99824353) * quickpow(5, aa[5], 99824353)) % 99824353); } return 0; }