Educational Codeforces Round 38 题解
2018-02-18 12:51
375 查看
总结
A由于阅读水平不够看了好久才看懂。这次的edu比之前我做的一场难了,D其实很简单但我往另一个方向想了,所以没有做出来,倒是E很快就切了。这是最终成绩:
题解
A. Word Correction
无聊题,怎么做都行。#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int n; char s[105]; bool check(char c) { return c=='a'||c=='e'||c=='i'||c=='o'||c=='u'||c=='y'; } int main() { scanf("%d",&n); scanf("%s",s+1); int flag=0; for (int i=1;i<=n;i++) { if (check(s[i])&&check(s[i-1])) continue; putchar(s[i]); } return 0; }
B. Run For Your Prize
直接双指针搞搞就好。#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=100005; const int inf=1000000; int n,a ; int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read(); for (int i=1;i<=n;i++) a[i]=read(); int l=0,r=n+1,ans=0; while (l+1<r) { if (a[l+1]-1<=inf-a[r-1]) l++,ans=max(ans,a[l]-1); else r--,ans=max(ans,inf-a[r]); } printf("%d",ans); return 0; }
C. Constructing Tests
列出式子后拆成完全平方式,然后通过枚举因数来暴力查找合法解即可。#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int n; int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { int T=read(); while (T--) { n=read(); if (!n) {printf("%d %d\n",1,1);continue;} int flag=0; for (int i=1;i*i<=n;i++) if (n%i==0) { if ((i&1)!=((n/i)&1)||i*i==n) continue; int x=(i+n/i)/2,y=(n/i-i)/2; if (x/(x/y)!=y) continue; printf("%d %d\n",x,x/y); flag=1;break; } if (!flag) puts("-1"); } return 0; }
D. Buy a Ticket
一开始想的是各种贪心,发现都不行。实际上只要新建一个超级点s,然后s往每个点连权值为点权的边。那么每个点到s的最短路就是该点的答案了。#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #define mp(x,y) make_pair(x,y) using namespace std; typedef long long LL; typedef pair<LL,int> pi; const int N=200005; const LL inf=(LL)1e18; int n,m,cnt,last ; LL dis ; bool vis ; struct edge{int to,next;LL w;}e[N*4]; priority_queue<pi> que; void addedge(int u,int v,LL w) { e[++cnt].to=v;e[cnt].w=w;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].w=w;e[cnt].next=last[v];last[v]=cnt; } void dij() { for (int i=1;i<=n;i++) dis[i]=inf; que.push(mp(0,0)); while (!que.empty()) { int x=que.top().second;que.pop(); while (!que.empty()&&vis[x]) x=que.top().second,que.pop(); if (vis[x]) break; vis[x]=1; for (int i=last[x];i;i=e[i].next) if (dis[x]+e[i].w<dis[e[i].to]) { dis[e[i].to]=dis[x]+e[i].w; que.push(mp(-dis[e[i].to],e[i].to)); } } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y;LL z;scanf("%d%d%I64d",&x,&y,&z); addedge(x,y,z*2); } for (int i=1;i<=n;i++) { LL w;scanf("%I64d",&w); addedge(0,i,w); } dij(); for (int i=1;i<=n;i++) printf("%I64d ",dis[i]); return 0; }
E. Max History
构造f的过程可以看成是在倒着维护一个单调递减的单调栈。我们可以单独考虑每一个数的贡献。一个数出现在单调栈里面当且仅当其前面没有不小于他的数。那么就可以把比他大的数全放在他后面,比他小的数就用隔板法算一算方案即可。#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int N=1000005; const int MOD=1000000007; int n,a ,jc ,ny ; int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int C(int n,int m) { return (LL)jc *ny[m]%MOD*ny[n-m]%MOD; } int main() { n=read(); for (int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); jc[0]=jc[1]=ny[0]=ny[1]=1; for (int i=2;i<=n;i++) jc[i]=(LL)jc[i-1]*i%MOD,ny[i]=(LL)(MOD-MOD/i)*ny[MOD%i]%MOD; for (int i=2;i<=n;i++) ny[i]=(LL)ny[i]*ny[i-1]%MOD; int ans=0; for (int i=1;i<=n;i++) { int j=i,s=i-1; while (j<n&&a[j+1]==a[j]) j++; (ans+=(LL)jc[s]*jc[n-s-1]%MOD*C(n,s)%MOD*a[i]%MOD*(j-i+1)%MOD)%=MOD; i=j; } (ans+=MOD-(LL)a *jc %MOD)%=MOD; printf("%d",ans); return 0; }
F. Erasing Substrings
这题比较厉害。最暴力的想法就是设dp[m][mask]表示在对一个前缀进行了mask里面的操作后,得到了最终串长度为m的最小前缀。这样的话我们还要储存一个字符串,时空复杂度显然不能接受。但不难发现对于两个状态dp[m][mask1]和dp[m][mask2],字典序较大的那个肯定不可能成为最终答案。那么我们就可以对每个状态只存一个布尔值,表示该状态能否成为最终串的前缀。
怎么计算这个呢?假设现在由长度m转移到长度m+1,那么我们就在所有状态的后一个字符里面找一个最小的,来作为第m+1个字符,然后更新dp[m+1][mask]的状态即可。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=5005; int n,m,r; char s ,ans ; bool f ,g ; int main() { scanf("%s",s+1);n=strlen(s+1); for (r=1;r*2<=n;r*=2); m=n-r+1; for (int i=0;i<r;i++) f[i]=1; for (int i=1;i<=m;i++) { ans[i]='z'; for (int j=0;j<r;j++) if (f[j]&&s[i+j]<ans[i]) ans[i]=s[i+j]; memset(g,0,sizeof(g)); for (int j=0;j<r;j++) if (f[j]&&s[i+j]==ans[i]&&!g[j]) { int w=r-1-j; for (int s=w;s;s=(s-1)&w) g[r-1-s]=1; g[r-1]=1; } for (int j=0;j<r;j++) f[j]=g[j]; } for (int i=1;i<=m;i++) putchar(ans[i]); return 0; }
G. Shortest Path Queries
题解相关文章推荐
- Educational Codeforces Round 22 题解
- Educational Codeforces Round 38 A - Word Correction
- Educational Codeforces Round 30 题解
- Educational Codeforces Round 38 A. Word Correction 水题
- Educational Codeforces Round 38 (Rated for Div. 2) D_Buy a Ticket_加源点Dijkstra
- Educational Codeforces Round 38 B - Run For Your Prize
- Educational Codeforces Round 19 题解【ABCDE】
- Educational Codeforces Round 38 C - Constructing Tests
- Educational Codeforces Round 38 [Codeforces938]
- Educational Codeforces Round 33 (Rated for Div. 2) 题解
- Educational Codeforces Round 31 题解
- Educational Codeforces Round 32[题解]
- Educational Codeforces Round 35 A B C D题解
- Educational Codeforces Round 6 题解&&代码
- Educational Codeforces Round 38 (Rated for Div. 2)A. Word Correction
- Educational Codeforces Round 38 C. Constructing Tests 思维
- Educational Codeforces Round 38 (Rated for Div. 2)
- Educational Codeforces Round 38 (Rated for Div. 2) 【B】 【双指针】
- Educational Codeforces Round 38 (Rated for Div. 2) A. Word Correction
- Educational Codeforces Round 38 (Rated for Div. 2) B. Run For Your Prize