T1.码灵鼠
手推f[2],f[3]可以发现f[i]=i-1
给出归纳证明:
为什么E(ai)+E(aj)==2E(ai)?因为i和j是相互独立的。
记得long long
#include<iostream> #include<cstdio> using namespace std; inline long long rd(){ long long ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } long long n; int main(){ n=rd(); for(int i=1;i<=n;i++){ long long x=rd(); printf("%lld ",x+1ll); } }
T2.So many prefix?
感觉是kmp,可是发现状态叠状态,很难做,暴力走人了
正解是这样的,那些重叠的状态,实际上i的上一个重叠位置就是fail[i],因此f[i]可以由f[fail[i]]转移来,这样就解决了。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=200005; char s[MAXN]; int fail[MAXN]; long long f[MAXN]; int main(){ scanf("%s",s+1); int lens=strlen(s+1); for(int i=2,j=0;i<=lens;i++){ while(j>0&&s[i]!=s[j+1]) j=fail[j]; if(s[i]==s[j+1]) j++; fail[i]=j; } long long ans=0; for(int i=1;i<=lens;i++) f[i]=f[fail[i]]+1ll*(!(i&1)); for(int i=1;i<=lens;i++) ans+=f[i]; cout<<ans; }
T3.Travel
之前A组的题,并没有写,考场上现推有点难受
考虑把R降序排序,从大到小枚举Ri,保证了上边界递减,然后从小到大枚举L,只考虑R大于Ri的部分,这样保证右边界一定为Ri,由于L是递增的,所以可以一条一条加边,第一次使得1和n连通便是L的最小值,这时候的L和Ri便是一组解,更新即可。
由于是从大到小枚举的R,所以每次更新,最后便是字典序最小的解。
复杂度O(αn^2)
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=1024; const int M=2048*4; int n,m; int frm[M],to[M],L[M],R[M],idr[M],idl[M]; bool cmpr(int x,int y){return R[x]>R[y];} bool cmpl(int x,int y){return L[x]<L[y];} int fa[MAXN]; void seti(){for(int i=1;i<=n;i++) fa[i]=i;} int fnd(int x){return x==fa[x]?x:fa[x]=fnd(fa[x]);} void cat(int x,int y){ x=fnd(x);y=fnd(y); if(x==y) return; fa[y]=x; } int solve(int down){ for(int i=1;i<=m;i++){ int k=idl[i]; if(R[k]<down) continue; cat(frm[k],to[k]); if(fnd(1)==fnd(n)) return L[k]; } return -1; } int ansl=0,ansr=-1; int main(){ n=rd();m=rd(); int x,y,l,r; for(int i=1;i<=m;i++){ frm[i]=rd();to[i]=rd(); L[i]=rd();R[i]=rd(); idl[i]=i;idr[i]=i; } sort(idl+1,idl+1+m,cmpl); sort(idr+1,idr+1+m,cmpr); int tmp=0; for(int i=1;i<=m;i++){ seti();int v=idr[i]; tmp=solve(R[v]); if(tmp==-1) continue; if(R[v]-tmp<ansr-ansl) continue; if(R[v]-tmp>=ansr-ansl) { ansr=R[v]; ansl=tmp; continue; } } if(ansr==-1) return puts("0"),0; printf("%d ",ansr-ansl+1); for(int i=ansl;i<=ansr;i++) printf("%d ",i); return 0; }