3.24模拟
前言
期望:100+20+68=188
實(shí)際:100+12+32=144
rnk4。
三高一碾壓五高二。
TLE掛了28分,失誤掛了16分。
繼前天的CF比賽之后再次分塊TLE而FST…
本機(jī)T3那28分得跑3.3-3.4s左右,但是由于本機(jī)比較老了,啟動(dòng)運(yùn)行似乎有一定時(shí)間,跑個(gè)樣例動(dòng)不動(dòng)都跑個(gè)0.8s-1s,所以覺(jué)得實(shí)測(cè)應(yīng)該是可過(guò)的。(更何況我這個(gè)復(fù)雜度Solution都提到了可以拿68)
然而現(xiàn)實(shí)很骨感…(為什么KH的機(jī)子不是太湖之光啊)
失誤如下:
解析
T1
確實(shí)是送分題,水到即使切掉也完全感覺(jué)不到安全感那種。
我的構(gòu)造方法是構(gòu)造一堆長(zhǎng)度為2的鏈,然后如果整除不了就找個(gè)葉子當(dāng)菊花花心接著構(gòu)造,極限數(shù)據(jù)大概是220個(gè)點(diǎn)左右。
題解的構(gòu)造上限也太驚人了些…思路倒是挺顯然,但是不明白怎么把路徑恰好用完的…
可能需要億些分類討論吧。那還不如我這個(gè)好寫(xiě)
T2
很巧妙的題。
大佬們都用SAM切掉了,只有我覺(jué)得是SA然后咋也不會(huì)…
(說(shuō)句閑話,這個(gè)題是怎么想到用SAM的啊…題意難道不和SA更配嗎?qwq)
正解還真是SA…
分治。
講完了。
然后思路就很自然了,遞歸找到當(dāng)前區(qū)間最小的 height\text{height}height,然后往兩邊遞歸計(jì)算,最后求出一個(gè) xxx 使得兩邊的最大值相等即可。
正解很好寫(xiě),補(bǔ)起來(lái)身心愉悅。
之前明明總結(jié)過(guò),這次還是想不起來(lái)…分治這種東西可能很難自然的想到(至少對(duì)我而言),需要刻意的去往這方面想一想。
T3
兩小時(shí)大分塊比暴力多12分,樂(lè)。
我的做法和題解本質(zhì)上差不多,我預(yù)處理的那個(gè)“轉(zhuǎn)移系數(shù)”其實(shí)就是題解的轉(zhuǎn)移矩陣。
這題一開(kāi)始我倒是想到矩乘了,但是一想到 m3m^3m3 的單次乘法復(fù)雜度我直接放棄…
題解一句輕描淡寫(xiě)“預(yù)處理出前綴和后綴的轉(zhuǎn)移矩陣即可,時(shí)間復(fù)雜度 O(nm2)O(nm^2)O(nm2)”。
你給我開(kāi)兩個(gè) nm2nm^2nm2 的數(shù)組試試!
可能還是我沒(méi)理解題解的做法吧…
那先講講我的吧。
先考慮暴力dp怎么做。
令 gig_igi? 表示以 iii 結(jié)尾的之前沒(méi)有出現(xiàn)過(guò)的子序列個(gè)數(shù)。
每次對(duì)于第 iii 個(gè)位置,設(shè) aia_iai? 上一次出現(xiàn)位置是 preprepre,則 gi=∑j=prei?1gjg_i=\sum_{j=pre}^{i-1}g_jgi?=∑j=prei?1?gj?。
然后前綴和優(yōu)化一些就 O(nq)O(nq)O(nq) 了。
這個(gè)東西轉(zhuǎn)化一下就變成:
有兩個(gè)數(shù)組 ansi,fians_i,f_iansi?,fi?, 注意這里iii的是一個(gè)字符而不是位置 ,每次添加一個(gè)字符 ccc,就令 fi←fc(i≠c),ansc←fcf_i\gets f_c(i\ne c),ans_c\gets f_cfi?←fc?(i?=c),ansc?←fc?。
然后發(fā)現(xiàn)這個(gè)東西的轉(zhuǎn)移過(guò)程十分固定,但是矩乘又存不下所有的矩陣,怎么辦呢?
考慮分塊。
設(shè)塊長(zhǎng)為 BBB ,考慮都有哪些復(fù)雜度。
由于矩乘復(fù)雜度太高,我們不再存矩陣,而是存對(duì)于每一個(gè) iii,初始時(shí)的 fi=1f_i=1fi?=1 能轉(zhuǎn)移到的 ansj,fjans_j,f_jansj?,fj? 的系數(shù) transansi,j,transfi,jtransans_{i,j},transf_{i,j}transansi,j?,transfi,j?。
前綴計(jì)算非常舒適,枚舉 iii,正著推一遍到塊的結(jié)尾記錄即可。復(fù)雜度 O(m(n+nBm))O(m(n+\dfrac{n}{B}m))O(m(n+Bn?m))。(前面的 mmm 是枚舉的 iii,后面是記錄的復(fù)雜度)
后綴計(jì)算比較難受,由于我們的遞推并不能倒著推,我們只能對(duì)于每一個(gè)塊的起始都重新暴力推一遍(我沒(méi)有想到題解那個(gè)奧妙重重的右乘矩陣),但好在我們推到這一塊的結(jié)尾的時(shí)候就可以利用后面一塊已經(jīng)算好的轉(zhuǎn)移系數(shù)直接轉(zhuǎn)移到最后(這個(gè)過(guò)程其實(shí)就是行矩陣乘轉(zhuǎn)移矩陣,復(fù)雜度 O(m2)O(m^2)O(m2)),因此總復(fù)雜度是 O(mnB(B+m2))O(m\dfrac{n}{B}(B+m^2))O(mBn?(B+m2))。
然后考慮回答詢問(wèn),我們需要暴力轉(zhuǎn)移散點(diǎn)(這個(gè)可以通過(guò)和題解類似的對(duì)全局記錄 fff 的累加和然后記錄每個(gè) fif_ifi? 相應(yīng)減去的 tagitag_itagi? 做到 O(len+m)O(len+m)O(len+m)),復(fù)雜度為 O(qB)O(qB)O(qB),整塊的轉(zhuǎn)移系數(shù)我們直接用就可以。
平衡一下令 B=m1.5B=m^{1.5}B=m1.5 復(fù)雜度達(dá)到最優(yōu),總復(fù)雜度 O((n+q)m1.5)O((n+q)m^{1.5})O((n+q)m1.5)。
(我本來(lái)以為這復(fù)雜度直接能切了,寫(xiě)完才發(fā)現(xiàn)我忽略了利用轉(zhuǎn)移系數(shù)轉(zhuǎn)移就需要 O(m2)O(m^2)O(m2) 的時(shí)間,所以至少是 O(qm2)O(qm^2)O(qm2) 的…但 68 都過(guò)不去是我沒(méi)想到的)
現(xiàn)在講講我對(duì)題解閱讀理解的心得。
題解的dp和我的本質(zhì)相同,然后把 ans,fans,fans,f 擺成一個(gè)行向量,每次就相當(dāng)于乘一個(gè)轉(zhuǎn)移矩陣。
這個(gè)矩陣差不多長(zhǎng)這樣:
(m=4,c=2)
然后乘完確實(shí)是它說(shuō)的那樣。
上面的第三個(gè)矩陣是一*二的結(jié)果。類似于 m+3=7m+3=7m+3=7 列的值加給了其他列。
上面的第三個(gè)矩陣是二*一的結(jié)果。類似于 m+3=7m+3=7m+3=7 行吸收了其他行。
但是知道了這個(gè)我還是不會(huì)。
提供這個(gè)現(xiàn)象,等待高人指點(diǎn)。
qwq
生成矩陣的代碼:
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) #define ok debug("OK\n") using namespace std;const int N=200+100; const int C=205; const int mod=998244353;inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m; struct matrix{int x,y;ll a[C<<1][C<<1];matrix(int c,int d){x=c;y=d;memset(a,0,sizeof(a));}matrix(){memset(a,0,sizeof(a));}void make(int c){x=y=m+m;memset(a,0,sizeof(a));for(int i=1;i<=m+m;i++) a[i][i]=1;//a[m+c][m+c]=0;for(int i=1;i<=m;i++){//if(i!=c) a[m+c][m+i]=1;}a[m+c][c]=1;}void print(){printf("\nprint: ---\n");for(int i=1;i<=x;i++){for(int j=1;j<=y;j++) printf("%lld ",a[i][j]);puts("");}return;} }; matrix operator * (const matrix &u,const matrix &v){matrix res(u.x,v.y);for(int k=1;k<=u.y;k++){for(int i=1;i<=u.x;i++){ll tmp=u.a[i][k];for(int j=1;j<=v.y;j++){(res.a[i][j]+=tmp*v.a[k][j])%=mod;}}}return res; } int a[N]; matrix pre[N],suf[N]; signed main(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);n=read();m=read();int ask=read();for(int i=1;i<=n;i++) a[i]=read();pre[0].x=pre[0].y=m+m;for(int i=1;i<=m+m;i++) pre[0].a[i][i]=1;for(int i=1;i<=n;i++){//printf("\n----------a=%d\n",a[i]);matrix o(m+m,m+m);o.make(a[i]);o.print();pre[i]=pre[i-1]*o;pre[i].print();}printf("---------------------------------------------------------------\n");suf[n+1].x=suf[n+1].y=m+m;for(int i=1;i<=m+m;i++) suf[n+1].a[i][i]=1;for(int i=n;i>=1;i--){printf("\n----------a=%d\n",a[i]);matrix o(m+m,m+m);o.make(a[i]);o.print();suf[i]=o*suf[i+1];suf[i].print();}matrix ori;ori.x=1;ori.y=m+m;for(int i=m+1;i<=m+m;i++) ori.a[1][i]=1;while(ask--){int pl=read(),add=read(),d=read();matrix res;res.make(add);res=res*suf[pl+1];res=res*pre[pl-1];//res.print();res=ori*res;printf("%lld\n",res.a[1][d]);}return 0; } /* */總結(jié)
- 上一篇: 设计师用的电脑配置(设计的电脑要什么配置
- 下一篇: 模板:LGV引理(线性代数)