Codeforces Round #604 (Div. 2)
A. Beautiful String
$solution:$
直接暴力即可。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } const int MAXN=100001; int N; char str[MAXN]; int main(){ int T=read(); while(T--){ scanf("%s",str+1);N=strlen(str+1); if(N==1){ if(str[1]=='?'){ printf("a\n"); continue; } printf("%c",str[1]); continue; }bool ff=1; for(int i=1;i<=N;i++){ if(str[i]!='?') continue; bool flag=0; for(char c='a';c<='c';c++){ if(str[i-1]!=c&&c!=str[i+1]){ str[i]=c; flag=1; break; } }if(!flag){ printf("-1\n");ff=0; break; } } for(int i=1;i<=N;i++) if(str[i]==str[i-1]){ printf("-1\n"); ff=0; break; } if(ff){ for(int i=1;i<=N;i++) printf("%c",str[i]); printf("\n"); } } return 0; }
B. Beautiful Numbers
$solution:$
直接模拟即可。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<climits> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } const int MAXN=200001; struct Segment{ int Minn[MAXN<<2],Maxn[MAXN<<2]; void clear(){memset(Minn,127/3,sizeof(Minn)),memset(Maxn,-127/3,sizeof(Maxn));return;} void Modify(int k,int l,int r,int ps,int w){ if(l==r){Minn[k]=Maxn[k]=w;return;} int mid=l+r>>1; if(ps<=mid) Modify(k<<1,l,mid,ps,w); if(mid<ps) Modify(k<<1|1,mid+1,r,ps,w); Minn[k]=min(Minn[k<<1],Minn[k<<1|1]); Maxn[k]=max(Maxn[k<<1],Maxn[k<<1|1]); } int QMaxn(int k,int l,int r,int x,int y){ if(x<=l&&r<=y) return Maxn[k]; int res=0,mid=l+r>>1; if(x<=mid) res=max(res,QMaxn(k<<1,l,mid,x,y)); if(mid<y) res=max(res,QMaxn(k<<1|1,mid+1,r,x,y)); return res; } int QMinn(int k,int l,int r,int x,int y){ if(x<=l&&r<=y) return Minn[k]; int res=INT_MAX,mid=l+r>>1; if(x<=mid) res=min(res,QMinn(k<<1,l,mid,x,y)); if(mid<y) res=min(res,QMinn(k<<1|1,mid+1,r,x,y)); return res; } }segment; int N,A[MAXN],ps[MAXN]; int main(){ int T=read(); while(T--){ segment.clear();N=read(); for(int i=1;i<=N;i++) A[i]=read(),ps[A[i]]=i; for(int i=1;i<=N;i++) segment.Modify(1,1,N,i,A[i]); int l=INT_MAX,r=INT_MIN; for(int i=1;i<=N;i++){ l=min(l,ps[i]),r=max(r,ps[i]); if(r-l+1==i&&segment.QMaxn(1,1,N,l,r)==i&&segment.QMinn(1,1,N,l,r)==1) printf("1"); else printf("0"); }printf("\n"); }return 0; }
C. Beautiful Regional Contest
$solution:$
考虑枚举金牌数量,发现银牌及铜牌分数线是单调增,直接维护即可。时间复杂度 $O(n)$ 。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } const int MAXN=200001; int A,B,C,D,Ans[MAXN],Ans1[MAXN],Ans2[MAXN]; void check(){ for(int i=1;i<A+B+C+D;i++) if(abs(Ans[i+1]-Ans[i])!=1) return; printf("YES\n"); for(int i=1;i<=Ans[0];i++) printf("%d ",Ans[i]);printf("\n");exit(0); } int main(){ A=read(),B=read(),C=read(),D=read(); int res=(A+B+C+D+1)/2; if(A+C==res){ Ans1[0]=0,Ans2[0]=0; for(int i=1;i<=A;i++) Ans1[++Ans1[0]]=0; for(int i=1;i<=C;i++) Ans1[++Ans1[0]]=2; for(int i=1;i<=B;i++) Ans2[++Ans2[0]]=1; for(int i=1;i<=D;i++) Ans2[++Ans2[0]]=3; int tot1=1,tot2=1;Ans[0]=0; while(tot1<=Ans1[0]&&tot2<=Ans2[0]) Ans[++Ans[0]]=Ans1[tot1],Ans[++Ans[0]]=Ans2[tot2],tot1++,tot2++; while(tot1<=Ans1[0]) Ans[++Ans[0]]=Ans1[tot1++]; while(tot2<=Ans2[0]) Ans[++Ans[0]]=Ans2[tot2++]; check(); } if(B+D==res){ Ans1[0]=0,Ans2[0]=0; for(int i=1;i<=B;i++) Ans1[++Ans1[0]]=1; for(int i=1;i<=D;i++) Ans1[++Ans1[0]]=3; for(int i=1;i<=A;i++) Ans2[++Ans2[0]]=0; for(int i=1;i<=C;i++) Ans2[++Ans2[0]]=2; int tot1=1,tot2=1;Ans[0]=0; while(tot1<=Ans1[0]&&tot2<=Ans2[0]) Ans[++Ans[0]]=Ans1[tot1],Ans[++Ans[0]]=Ans2[tot2],tot1++,tot2++; while(tot1<=Ans1[0]) Ans[++Ans[0]]=Ans1[tot1++]; while(tot2<=Ans2[0]) Ans[++Ans[0]]=Ans2[tot2++]; check(); } printf("NO\n");return 0; return 0; }
D. Beautiful Sequence
$solution:$
考虑奇偶位拆开考虑,因为在奇位或偶位都呈不下降,且差为 $0,2$ ,暴力维护最后 $check$ 即可,时间复杂度 $O(n)$ 。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } const int MAXN=200001; int A,B,C,D,Ans[MAXN],Ans1[MAXN],Ans2[MAXN]; void check(){ for(int i=1;i<A+B+C+D;i++) if(abs(Ans[i+1]-Ans[i])!=1) return; printf("YES\n"); for(int i=1;i<=Ans[0];i++) printf("%d ",Ans[i]);printf("\n");exit(0); } int main(){ A=read(),B=read(),C=read(),D=read(); int res=(A+B+C+D+1)/2; if(A+C==res){ Ans1[0]=0,Ans2[0]=0; for(int i=1;i<=A;i++) Ans1[++Ans1[0]]=0; for(int i=1;i<=C;i++) Ans1[++Ans1[0]]=2; for(int i=1;i<=B;i++) Ans2[++Ans2[0]]=1; for(int i=1;i<=D;i++) Ans2[++Ans2[0]]=3; int tot1=1,tot2=1;Ans[0]=0; while(tot1<=Ans1[0]&&tot2<=Ans2[0]) Ans[++Ans[0]]=Ans1[tot1],Ans[++Ans[0]]=Ans2[tot2],tot1++,tot2++; while(tot1<=Ans1[0]) Ans[++Ans[0]]=Ans1[tot1++]; while(tot2<=Ans2[0]) Ans[++Ans[0]]=Ans2[tot2++]; check(); } if(B+D==res){ Ans1[0]=0,Ans2[0]=0; for(int i=1;i<=B;i++) Ans1[++Ans1[0]]=1; for(int i=1;i<=D;i++) Ans1[++Ans1[0]]=3; for(int i=1;i<=A;i++) Ans2[++Ans2[0]]=0; for(int i=1;i<=C;i++) Ans2[++Ans2[0]]=2; int tot1=1,tot2=1;Ans[0]=0; while(tot1<=Ans1[0]&&tot2<=Ans2[0]) Ans[++Ans[0]]=Ans1[tot1],Ans[++Ans[0]]=Ans2[tot2],tot1++,tot2++; while(tot1<=Ans1[0]) Ans[++Ans[0]]=Ans1[tot1++]; while(tot2<=Ans2[0]) Ans[++Ans[0]]=Ans2[tot2++]; check(); } printf("NO\n");return 0; return 0; }
E. Beautiful Mirrors
$solution:$
设 $f_i$ 表示从 $i$ 到 $N$ 的期望步数,则 $f_i=p_i\cdot f_{i+1}+(1-p_i)\cdot f_1$ 。
考虑将 $f_i$ 表示成 $a_i\cdot f_1+b_i$ 的形式。推一下 $a_i,b_i$ 后 $f_1=a_1\cdot f_1+b_1$ ,所以 $f_1=\dfrac{b_1}{1-a_1}$ 。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define int long long #define mod 998244353 using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } const int MAXN=200011; int Mod(int x){return (((x%mod)+mod)%mod);} int A[MAXN],B[MAXN],P[MAXN]; int ksm(int a,int b){ int ans=1; while(b){ if(b&1) ans*=a,ans%=mod; a*=a,a%=mod;b>>=1; }return ans; } int N; signed main(){ N=read(); for(int i=1;i<=N;i++){ int u=read(); P[i]=u*ksm(100,mod-2)%mod; } for(int i=N;i>=1;i--){ A[i]=Mod((A[i+1]*P[i]%mod)+Mod(1-P[i])),B[i]=1+B[i+1]*P[i],B[i]%=mod; } int fz=B[1],fm=Mod(1-A[1]); printf("%lld\n",fz*ksm(fm,mod-2)%mod);return 0; }
F. Beautiful Bracket Sequence (easy version)
$solution:$
考虑深度最大即为在字符串中为 $(((((()))))$ ,深度=左括号个数=右括号个数。
考虑在枚举,若 $[1-i]$ 中出现 $j$ 个左括号,$(i,N]$ 中出现 $j$ 个右括号,其计算个数可以通过简单的组合数得到。时间复杂度 $O(n^2)$ 。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define int long long #define mod 998244353 using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=100010; int Ans,N,S1[MAXN],S2[MAXN],S3[MAXN],inv[MAXN],ifac[MAXN],fac[MAXN]; int C(int a,int b){return a<b?0:fac[a]*ifac[b]%mod*ifac[a-b]%mod;} char str[MAXN]; signed main(){ // freopen("2.in","r",stdin); fac[0]=fac[1]=ifac[0]=ifac[1]=inv[1]=1; for(int i=2;i<MAXN;i++) fac[i]=fac[i-1]*i%mod,inv[i]=(mod-mod/i)*inv[mod%i]%mod,ifac[i]=ifac[i-1]*inv[i]%mod; scanf("%s",str+1);N=strlen(str+1); for(int i=1;i<=N;i++){ S1[i]=S1[i-1],S2[i]=S2[i-1],S3[i]=S3[i-1]; if(str[i]=='(') S1[i]++;if(str[i]==')') S2[i]++;if(str[i]=='?') S3[i]++; } for(int i=1;i<=N;i++){ for(int j=1;j<=i;j++){ int res1=j-S1[i],res2=j-(S2[N]-S2[i]); int nw1=S3[i],nw2=S3[N]-S3[i]; if(res1<0||res2<0||nw1<0||nw2<0) continue; if(res1>nw1||res2>nw2) continue; Ans+=C(nw1,res1)*C(nw2,res2)%mod*j%mod;Ans%=mod; } }printf("%lld\n",Ans);return 0; }