【考試總結】2022-03-04
阿新 • • 發佈:2022-03-04
A.字首 B.斐波那契 C.過路費
字首
使用 \(ex-kmp\) 求出來每個字尾 和全串的 \(\rm LCP\) 長度,那麼對應 \(len\in[1,LCP]\) 的字首又出現了一次
Code Display
const int N=1e7+10; int z[N],ans,ton[N],n; char s[N]; signed main(){ freopen("pre.in","r",stdin); freopen("pre.out","w",stdout); scanf("%s",s+1); n=strlen(s+1); z[1]=n; for(int i=2,l=0,r=0;i<=n;++i){ if(i<=r) z[i]=min(z[i-l+1],r-i+1); while(i+z[i]<=n&&s[z[i]+1]==s[i+z[i]]) ++z[i]; if(i+z[i]-1>r) l=i,r=i+z[i]-1; } for(int i=1;i<=n;++i) ton[z[i]]++; Down(i,n,1) ton[i]+=ton[i+1],ans+=ton[i]; print(ans); return 0; }
斐波那契
使用線段樹維護矩陣即可,每次區間加定值時可以乘一個對應次數的轉移矩陣
那麼區間求 \(\rm Fib\) 的和就對應區間矩陣的和
Code Display
const int N=1e5+10; struct mat{ int a[2][2]; mat(){a[0][0]=a[0][1]=a[1][0]=a[1][1]=0;} mat(int b,int c,int d,int e){a[0][0]=b; a[0][1]=c; a[1][0]=d; a[1][1]=e;} bool operator ==(const mat &e)const{ rep(i,0,1) rep(j,0,1) if(a[i][j]!=e.a[i][j]) return 0; return 1; } }pw[40],val[N<<2],tag[N<<2]; inline mat Mul(mat &a,mat &b){ mat c; c.a[0][0]=add(mul(a.a[0][0],b.a[0][0]),mul(a.a[0][1],b.a[1][0])); c.a[0][1]=add(mul(a.a[0][0],b.a[0][1]),mul(a.a[0][1],b.a[1][1])); c.a[1][0]=add(mul(a.a[1][0],b.a[0][0]),mul(a.a[1][1],b.a[1][0])); c.a[1][1]=add(mul(a.a[1][0],b.a[0][1]),mul(a.a[1][1],b.a[1][1])); return c; } inline mat Plus(mat a,mat b){ mat c; rep(i,0,1) rep(j,0,1) c.a[i][j]=add(a.a[i][j],b.a[i][j]); return c; } inline mat Minus(mat a,mat b){ mat c; rep(i,0,1) rep(j,0,1) c.a[i][j]=del(a.a[i][j],b.a[i][j]); return c; } inline mat Get(int n){ mat res=mat(1,0,0,1); for(int i=1;i<=32;++i) if(n>>(i-1)&1) res=Mul(res,pw[i]); return res; } int a[N],n,Q; #define ls p<<1 #define rs p<<1|1 #define lson ls,l,mid #define rson rs,mid+1,r inline void push_tag(int p,mat now){ val[p]=Mul(val[p],now); tag[p]=Mul(tag[p],now); return ; } inline void push_down(int p){ if(tag[p]==pw[0]) return ; push_tag(ls,tag[p]); push_tag(rs,tag[p]); tag[p]=pw[0]; return ; } inline void push_up(int p){val[p]=Plus(val[ls],val[rs]);} inline void build(int p,int l,int r){ tag[p]=pw[0]; if(l==r) return val[p]=Get(a[l]-1),void(); int mid=(l+r)>>1; build(lson); build(rson); return push_up(p); } inline void upd(int st,int ed,mat d,int p=1,int l=1,int r=n){ if(st<=l&&r<=ed) return push_tag(p,d); int mid=(l+r)>>1; push_down(p); if(st<=mid) upd(st,ed,d,lson); if(ed>mid) upd(st,ed,d,rson); return push_up(p); } inline mat query(int st,int ed,int p=1,int l=1,int r=n){ if(st<=l&&r<=ed) return val[p]; int mid=(l+r)>>1; push_down(p); if(ed<=mid) return query(st,ed,lson); if(st>mid) return query(st,ed,rson); return Plus(query(st,ed,lson),query(st,ed,rson)); } #undef ls #undef rs #undef lson #undef rson signed main(){ freopen("fib.in","r",stdin); freopen("fib.out","w",stdout); n=read(); Q=read(); rep(i,1,n) a[i]=read(); pw[0]=mat(1,0,0,1); pw[1]=mat(0,1,1,1); for(int i=2;i<=35;++i) pw[i]=Mul(pw[i-1],pw[i-1]); build(1,1,n); while(Q--){ if(read()-1){ int l=read(),r=read(); mat ans=query(l,r); print(add(ans.a[0][0],ans.a[1][0])); }else{ int l=read(),r=read(); upd(l,r,Get(read())); } } return 0; }
過路費
考慮列舉最短路上作為第 \(k\) 大的邊的權值 \(v\),全圖的邊都減掉 \(v\) 跑 \(Dijkstra\) 將得數加 \(kv\) 即可
這樣做正確的原因是如果少於 \(k\) 條邊不小於 \(v\) 那麼必然附加的 \(kv\) 是冗餘的,而如果超過 \(k\) 條邊大於 \(v\) 那麼將 \(v\) 取更大的值時必然有更好的結果
Code Display
const int N=2010; int S,T,n,m,k,b[N]; vector<pair<int,int> > G[N]; int dis[N]; int u[N],v[N],w[N]; inline void rebuild(int d){ for(int i=1;i<=n;++i) G[i].clear(); for(int i=1;i<=m;++i){ G[u[i]].push_back({v[i],max(0ll,w[i]-d)}); } return ; } bool vis[N]; signed main(){ freopen("fee.in","r",stdin); freopen("fee.out","w",stdout); n=read(); m=read(); k=read(); S=read(); T=read(); int cnt_val=0; for(int i=1;i<=m;++i){ u[i]=read(); v[i]=read(); w[i]=read(); b[++cnt_val]=w[i]; } int ans=0x3f3f3f3f3f3f3f3f; sort(b+1,b+cnt_val+1); cnt_val=unique(b+1,b+cnt_val+1)-b-1; for(int p=1;p<=cnt_val;++p){ rebuild(b[p]); memset(dis,0x3f,sizeof(dis)); priority_queue<pair<int,int> >q; q.push({0,S}); dis[S]=0; rep(i,1,n) vis[i]=0; while(q.size()){ int fr=q.top().sec; q.pop(); if(vis[fr]) continue; vis[fr]=1; for(auto e:G[fr]){ if(dis[e.fir]>dis[fr]+e.sec){ dis[e.fir]=dis[fr]+e.sec; q.push(make_pair(-dis[e.fir],e.fir)); } } } ckmin(ans,dis[T]+k*b[p]); } print(ans); return 0; }
這套題目相信很多同學聯賽做和現在做得分並不會有什麼不同