The 2022 ICPC Asia Regionals Online Contest (II) 2022ICPC第二场网络赛 ABEFGJKL题解
文章目錄
- A Yet Another Remainder【費(fèi)馬小定理】
- B Non-decreasing Array【線性DP】
- E An Interesting Sequence【簽到】
- F Infinity Tree 【簽到】
- G Good Permutation【排列組合,樹(shù)形結(jié)構(gòu)】
- J A Game about Increasing Sequences【博弈】
- K Black and White Painting【模擬】
- L Quadruple【簡(jiǎn)單容斥】
A Yet Another Remainder【費(fèi)馬小定理】
首先明確x是無(wú)法求解的,當(dāng)x大于1e6,一共有1e4個(gè)方程組,不可能求解1e6個(gè)未知數(shù)。
因?yàn)轭}目將x的各個(gè)十進(jìn)制位拆開(kāi),并且按照不同的步長(zhǎng)分組,因此可能是通過(guò)計(jì)算組內(nèi)的值,再將各組的值拼接起來(lái)得到xmodpx\ mod\ px?mod?p的結(jié)果。
ppp都是小于100的數(shù),modpmod\ pmod?p的結(jié)果必然都是100以內(nèi)的值,因此推測(cè)modpmod\ pmod?p的結(jié)果可能會(huì)產(chǎn)生某種規(guī)律,比如形成循環(huán)節(jié)出現(xiàn)。
到這里沒(méi)有什么新的思路,因此可以翻翻書(shū)找找跟質(zhì)數(shù)和模數(shù)有關(guān)的定理來(lái)輔助解題…最常見(jiàn)最相關(guān)的就是費(fèi)馬小定理了!
費(fèi)馬小定理: 如果p是一個(gè)質(zhì)數(shù),而整數(shù)a不是p的倍數(shù),則有a(p?1)≡1a^{(p-1)}≡1a(p?1)≡1(mod p)。
費(fèi)馬小定理中的ppp就是我們題目中的ppp,那么aaa可以是什么呢?題目將xxx按照10進(jìn)制進(jìn)行拆分,因此aaa可以是10i10^i10i,可惜發(fā)現(xiàn)p=5p=5p=5時(shí)10i10^i10i是5的倍數(shù),但是!題目非常細(xì)心地將p=5p=5p=5的情況給剔除掉了!因此可以確定這個(gè)方向應(yīng)該是正確的!
接下來(lái)就是利用費(fèi)馬小定理給xmodpx\ mod\ px?mod?p進(jìn)行分組求和了。因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">10p?1≡1(modp)10^{p-1}≡1(mod\ p)10p?1≡1(mod?p),因此有102(p?1)≡(modp),103(p?1)≡(modp)...10s(p?1)≡(modp)10^{2(p-1)}≡(mod\ p),\ 10^{3(p-1)}≡(mod\ p)...\ 10^{s(p-1)}≡(mod\ p)102(p?1)≡(mod?p),?103(p?1)≡(mod?p)...?10s(p?1)≡(mod?p),其中s表示最后一項(xiàng)。因此可以將10k(p?1)≡1(modp)10^{k(p-1)}≡1(mod\ p)10k(p?1)≡1(mod?p)當(dāng)成一組同時(shí)求解。而在第p?1p-1p?1行,給定的恰好是以p?1p-1p?1為步長(zhǎng)的十進(jìn)制位的和。
因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">x=10n?1?a1+10n?2?a2+...+10n?i?ai+100?anx=10^{n-1}*a^1+10^{n-2}*a^2+...+ 10^{n-i}*a^i+10^0*a^nx=10n?1?a1+10n?2?a2+...+10n?i?ai+100?an,可知找到10s(p?1)10^{s(p-1)}10s(p?1)對(duì)應(yīng)的是a數(shù)組的第n?s(p?1)n-s(p-1)n?s(p?1)項(xiàng),即bp?1,n?s(p?1)b_{p-1,n-s(p-1)}bp?1,n?s(p?1)?。
將10k(p?1)+1,k=0,1,2,...,s10^{k(p-1)+1},\ k=0,1,2,...,s10k(p?1)+1,?k=0,1,2,...,s的項(xiàng)作為一組,將10k(p?1)+2,k=0,1,2,...,s10^{k(p-1)+2},\ k=0,1,2,...,s10k(p?1)+2,?k=0,1,2,...,s作為一組。
即將x拆解為(a1+a1+(p?1)+a1+2(p?1)+...+a1+s(p?1))?10(n?1)%(p?1))+(a2+a2+(p?1)+a2+2(p?1)+...+a2+s(p?1))?10(n?2)%(p?1))+...+(ap?1+ap?1+(p?1)+ap?1+2(p?1)+...+ap?1+s(p?1))?10(n?p+1)%(p?1))(a_1+a_{1+ (p-1)}+a_{1+2(p-1)}+...+a_{1+s(p-1)})*10^{(n-1)\%(p-1)})+\\(a_2+a_{2+ (p-1)}+a_{2+2(p-1)}+...+a_{2+s(p-1)})*10^{(n-2)\%(p-1)})+\\...+\\(a_{p-1}+a_{p-1+ (p-1)}+a_{p-1+2(p-1)}+...+a_{p-1+s(p-1)})*10^{(n-p+1)\%(p-1)})(a1?+a1+(p?1)?+a1+2(p?1)?+...+a1+s(p?1)?)?10(n?1)%(p?1))+(a2?+a2+(p?1)?+a2+2(p?1)?+...+a2+s(p?1)?)?10(n?2)%(p?1))+...+(ap?1?+ap?1+(p?1)?+ap?1+2(p?1)?+...+ap?1+s(p?1)?)?10(n?p+1)%(p?1))
用b表示為bp?1,1?10(n?1)%(p?1)+bp?1,2?10(n?2)%(p?1)+...+bp?1,p?1?10(n?p+1)%(p?1)b_{p-1,1}*10^{(n-1)\%(p-1)}+b_{p-1,2}*10^{(n-2)\%(p-1)}+...+b_{p-1,p-1}*10^{(n-p+1)\%(p-1)}bp?1,1??10(n?1)%(p?1)+bp?1,2??10(n?2)%(p?1)+...+bp?1,p?1??10(n?p+1)%(p?1)
B Non-decreasing Array【線性DP】
賽時(shí)沒(méi)過(guò)題,一直往區(qū)間dp想,復(fù)雜度是n4n^4n4的,很難優(yōu)化。但是dp最簡(jiǎn)單的就是從頭到尾推的線性dp啊…下次思路卡住就看看書(shū)吧!dp入門!
先簡(jiǎn)單地證明一下,將一個(gè)數(shù)字刪除總是會(huì)得到更好的結(jié)果
假設(shè)現(xiàn)在的數(shù)組是a,b,c(c>=b>=a)a,b,c(c>=b>=a)a,b,c(c>=b>=a),三個(gè)數(shù)對(duì)答案的貢獻(xiàn)是(c?b)2+(b?a)2(c-b)^2+(b-a)^2(c?b)2+(b?a)2,而將中間的數(shù)刪除之后,對(duì)答案的貢獻(xiàn)變成(c?a)2=((c?b)+(b?a))2=(c?b)2+(b?a)2+2(c?b)(b?a)(c-a)^2=((c-b)+(b-a))^2=(c-b)^2+(b-a)^2+2(c-b)(b-a)(c?a)2=((c?b)+(b?a))2=(c?b)2+(b?a)2+2(c?b)(b?a),因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">c>=b,b>=ac>=b,b>=ac>=b,b>=a,因此每刪除一個(gè)中間數(shù),答案就相比原來(lái)增加2*中間數(shù)與前數(shù)的差*后數(shù)與前數(shù)的差。刪除一個(gè)數(shù),答案增加如上所述,而改變一個(gè)數(shù),其實(shí)最佳方式就是直接將其變成它的某個(gè)相鄰數(shù),因?yàn)橄噜彶钭優(yōu)?,對(duì)答案不再有貢獻(xiàn),其實(shí)和刪除的操作是一樣的。因此第kkk次操作,就是選兩個(gè)數(shù)刪除掉。
先記錄起始的答案,接下來(lái)只有相鄰差有用,而原來(lái)的數(shù)已經(jīng)沒(méi)有用了,因此直接記錄它們的相鄰差數(shù)組difdifdif即可。接下來(lái)的問(wèn)題就像石子合并:一開(kāi)始有n?1n-1n?1堆石子,每堆石子的數(shù)量為dif[i]dif[i]dif[i],每次選擇相鄰的兩堆石子i,ji,ji,j,答案增加2?dif[i]?dif[j]2*dif[i]*dif[j]2?dif[i]?dif[j],然后將兩堆石子合并起來(lái)。
f[i][j]f[i][j]f[i][j]表示從第一堆石子到第iii堆石子,已經(jīng)合并了jjj堆石子獲得的最大答案。
接下來(lái)思考如何更新f[i][j]f[i][j]f[i][j]。只需要考慮最后第iii堆和前面多少堆連續(xù)合并在一起即可。
依次類推即可。
note: 可預(yù)處理出數(shù)組g[i][j]g[i][j]g[i][j]表示從iii到jjj連續(xù)段石子合并的答案。
#include<bits/stdc++.h> #define LL long long using namespace std; const int N = 110; LL g[N][N], f[N][N], dif[N], pre[N]; int a[N]; int main() {int n; cin >> n;for(int i = 1; i <= n; i ++) cin >> a[i];LL ans = 0;for(int i = 1; i < n; i ++) dif[i] = a[i + 1] - a[i], ans += dif[i] * dif[i], pre[i] = pre[i - 1] + dif[i];//預(yù)處理出從i到j(luò)連續(xù)段的答案貢獻(xiàn)n --;for(int i = 1; i < n; i ++)for(int j = i + 1; j <= n; j ++)g[i][j] = g[i][j - 1] + 2 * dif[j] * (pre[j - 1] - pre[i - 1]);for(int i = 1; i <= n; i ++)for(int j = 0; j < i; j ++)for(int k = 1; k <= i; k ++)if(j - i + k >= 0)f[i][j] = max(f[i][j], f[k - 1][j - i + k] + g[k][i]);for(int i = 1; i <= n + 1; i ++){printf("%lld\n", ans + f[n][min(i * 2, n - 1)]);}return 0; }E An Interesting Sequence【簽到】
找到第一個(gè)和k互質(zhì)的數(shù),然后一直放2323…或者3232…即可。
F Infinity Tree 【簽到】
觀察發(fā)現(xiàn),第n秒樹(shù)的大小為(k+1)n(k+1)^n(k+1)n,不難推出,節(jié)點(diǎn)x的父親節(jié)點(diǎn)為(x?t?1)/k+1(x - t - 1) / k + 1(x?t?1)/k+1,其中ttt為第一個(gè)小于x的(k+1)n(k+1)^n(k+1)n,每次暴力找到第一個(gè)小于x和小于y的節(jié)點(diǎn),一直往上跳即可。
G Good Permutation【排列組合,樹(shù)形結(jié)構(gòu)】
考慮最簡(jiǎn)單的情況,只有[1,n][1,n][1,n]一個(gè)區(qū)間,答案就是n!n!n!。如果[1,n][1,n][1,n]中包含333個(gè)區(qū)間限制,恰好覆蓋[1,n][1,n][1,n]整個(gè)區(qū)間,長(zhǎng)度分別為len1,len2,len3len1,len2,len3len1,len2,len3,答案是3!?len1!?len2!?len3!3!*len1!*len2!*len3!3!?len1!?len2!?len3!。3!3!3!表示將3個(gè)限制區(qū)間在[1,n][1,n][1,n]之間進(jìn)行全排列,len1!len1!len1!表示被分到第1個(gè)區(qū)間的連續(xù)數(shù)字的排列方案。但是如果區(qū)間1還有2個(gè)小區(qū)間,長(zhǎng)度分別為len11,len12len11,len12len11,len12,這時(shí)區(qū)間1的方案數(shù)就變成2!?len11!?len122!*len11!*len122!?len11!?len12,全區(qū)間的方案數(shù)也會(huì)從3!?len1!?len2!?len3!3!*len1!*len2!*len3!3!?len1!?len2!?len3!變成3!?2!?len11!?len12?len2!?len3!3!*2!*len11!*len12*len2!*len3!3!?2!?len11!?len12?len2!?len3!。因此應(yīng)該先將小區(qū)間更新,更新完小區(qū)間再用小區(qū)間更新大區(qū)間。
因?yàn)槊總€(gè)區(qū)間只有包含和并列關(guān)系,因此構(gòu)成了樹(shù)形結(jié)構(gòu),可以給每個(gè)區(qū)間一個(gè)編號(hào)。然后排序亂搞一通獲得一棵樹(shù)結(jié)構(gòu)。先利用set將區(qū)間去重,然后按照左端點(diǎn)從小到大,右端點(diǎn)從大到小排序。這樣排序可保證后面的區(qū)間必然不是前面的區(qū)間的父親,因此每次記錄上一次排序結(jié)束的區(qū)間節(jié)點(diǎn)preprepre,當(dāng)前區(qū)間的節(jié)點(diǎn)為curcurcur,則curcurcur的父親就是curcurcur和preprepre的最近公共祖先,因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">preprepre和curcurcur區(qū)間中間已經(jīng)沒(méi)有隔著其他區(qū)間了。
#include<bits/stdc++.h> #define LL long long using namespace std; const int N = 1e6 + 10, mod = 1e9 + 7; struct Seg {int l, r, len, fa;bool operator<(const Seg &x)const{if(l == x.l) return x.r < r;return l < x.l;}bool operator=(const Seg &x)const{return l == x.l && r == x.r;} }seg[N]; set<Seg> tmp_seg; int n, m; int fac[N]; vector<int> son[N]; int dfs(int u) {int ans = 1, len = 0;for(auto v : son[u]){ans = 1ll * ans * dfs(v) % mod;len += seg[v].len;}int left = seg[u].len - len, sz = left + son[u].size();ans = 1ll * fac[sz] * ans % mod;return ans; } int main() {scanf("%d%d", &n, &m);for(int i = 1; i <= m; i ++){int l, r; scanf("%d%d", &l, &r);if(l == 1 && r == n) continue;tmp_seg.insert({l, r, r - l + 1, 0});}int cnt = 1;seg[cnt].l = 1, seg[cnt].r = n, seg[cnt].len = n;for(auto it : tmp_seg){int pre = cnt; cnt ++;seg[cnt].l = it.l, seg[cnt].r = it.r, seg[cnt].len = it.len;while(seg[pre].r < seg[cnt].r) pre = seg[pre].fa;seg[cnt].fa = pre;son[pre].push_back(cnt);}fac[0] = 1;for(int i = 1; i <= max(m, n); i ++) fac[i] = 1ll * fac[i - 1] * i % mod;printf("%d\n", dfs(1));return 0; }J A Game about Increasing Sequences【博弈】
可以發(fā)現(xiàn),只有數(shù)列從左向右最長(zhǎng)的一段遞增序列和從右向左最長(zhǎng)的一段遞增序列有用。
考慮這兩段序列的起始元素,如果兩個(gè)元素大小相同,且兩段序列中存在一段奇數(shù)長(zhǎng)度的序列則先手必勝。
否則:
如果大的那個(gè)元素對(duì)應(yīng)的序列長(zhǎng)度為奇數(shù),那么先手必勝;
不然先手必然選小的那個(gè)元素,然后輪到后手選;
我們直接模擬一遍即可得出結(jié)果。
K Black and White Painting【模擬】
因?yàn)檎麄€(gè)網(wǎng)格的大小只有200*200,因此考慮標(biāo)記每個(gè)網(wǎng)格的有貢獻(xiàn)的邊和圓弧來(lái)統(tǒng)計(jì)答案。用左下角的點(diǎn)來(lái)表示網(wǎng)格。對(duì)于每個(gè)網(wǎng)格,直線邊有上下左右四條邊,網(wǎng)格內(nèi)可能存在四種圓弧。因此只需要考慮邊和圓弧的所有組合情況即可。
某個(gè)網(wǎng)格里圓弧組合為02 或者13,則四條邊和所有圓弧都會(huì)被覆蓋失效。
若整個(gè)網(wǎng)格都某個(gè)正方形覆蓋,那么不管網(wǎng)格里的所有圓弧都會(huì)失效,枚舉網(wǎng)格四條邊看是否存在一條正方形邊,且不會(huì)被其他的圖形覆蓋。比如判斷網(wǎng)格左邊是否有貢獻(xiàn),要檢查:網(wǎng)格左側(cè)有正方形邊,當(dāng)前網(wǎng)格左側(cè)的網(wǎng)格沒(méi)有整個(gè)網(wǎng)格被覆蓋且沒(méi)有23形狀的圓弧。
存在兩段圓弧(除了02組合和13組合的其他圓弧組合情況),都會(huì)有1/3的圓弧貢獻(xiàn)
存在一段圓弧,都會(huì)有1/2的圓弧貢獻(xiàn)。
L Quadruple【簡(jiǎn)單容斥】
首先不難想到處理出ICPC的前綴和來(lái)對(duì)付區(qū)間詢問(wèn),但是這樣會(huì)算多一些,因?yàn)閰^(qū)間外的I與區(qū)間內(nèi)的CPC組成的ICPC、區(qū)間外的IC和區(qū)間內(nèi)的PC組成的ICPC和區(qū)間外的ICP和區(qū)間內(nèi)的C組成的ICPC都會(huì)被算進(jìn)去。于是我們減掉這些即可。CPC的方案數(shù)和PC的方案數(shù)計(jì)算方法也是類似的。
#include<bits/stdc++.h> #define LL long long using namespace std; const int N = 2e6 + 10, mod = 998244353; char s[N]; int n, q, u[N], v[N]; struct Int {int a;Int(){}Int(int _a){a = _a;}Int operator + (const Int &b)const {return Int{(a + b.a) % mod};}Int operator - (const Int &b)const {return Int{(a - b.a + mod) % mod};}Int operator * (const Int &b)const {return Int{1ll * a * b.a % mod};} }I[N], C[N], P[N], IC[N], CP[N], PC[N], ICP[N], CPC[N], ICPC[N]; int get(int l, int r) {Int sicpc = ICPC[r] - ICPC[l - 1];Int spc = PC[r] - PC[l - 1] - P[l - 1] * (C[r] - C[l - 1]);Int scpc = CPC[r] - CPC[l - 1] - CP[l - 1] * (C[r] - C[l - 1]) - C[l - 1] * spc;sicpc = sicpc - scpc * I[l - 1] - IC[l - 1] * spc - ICP[l - 1] * (C[r] - C[l - 1]);return sicpc.a; } int main() {scanf("%d%d", &n, &q);scanf("%s", s + 1);int x, a, b, p, ans = 0;scanf("%d%d%d%d", &x, &a, &b, &p);for(int i = 1; i <= n; i ++){ICPC[i] = ICPC[i - 1] + ICP[i - 1] * (s[i] == 'C');ICP[i] = ICP[i - 1] + IC[i - 1] * (s[i] == 'P'), CPC[i] = CPC[i - 1] + CP[i - 1] * (s[i] == 'C');IC[i] = IC[i - 1] + I[i - 1] * (s[i] == 'C'), CP[i] = CP[i - 1] + C[i - 1] * (s[i] == 'P'), PC[i] = PC[i - 1] + P[i - 1] * (s[i] == 'C');I[i] = I[i - 1] + (s[i] == 'I'), C[i] = C[i - 1] + (s[i] == 'C'), P[i] = P[i - 1] + (s[i] == 'P');}for(int i = 1; i <= n; i ++) u[i] = x = (1ll * a * x + b) % p, u[i] = u[i] % n + 1;for(int i = 1; i <= n; i ++) v[i] = x = (1ll * a * x + b) % p, v[i] = v[i] % n + 1;for(int i = 1; i <= n; i ++) ans = (ans + get(min(u[i], v[i]), max(u[i], v[i]))) % mod;printf("%d\n", ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的The 2022 ICPC Asia Regionals Online Contest (II) 2022ICPC第二场网络赛 ABEFGJKL题解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 大学生职业生涯规划书PPT模板
- 下一篇: SAP业务事务代码