Educational Codeforces Round 70 题解
噩梦场。
题目出奇的难,好像一群外国老哥看 A 看着看着就哭了……
A
找到 \(b\) 最低的 \(1\),这个 \(1\) 肯定要跟 A 中的一个 \(1\) 搭配,而且是能搭配的 \(1\) 中最低的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010,mod=998244353;
#define MP make_pair
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int t,n,m;
char a[maxn],b[maxn];
int main(){
t=read();
while(t--){
scanf("%s",a+1);scanf("%s",b+1);
n=strlen(a+1);m=strlen(b+1);
int at,ans=0;
ROF(i,m,1) if(b[i]=='1'){at=n-(m-i);break;}
while(at>0 && a[at]=='0') at--,ans++;
printf("%d\n",ans);
}
}
B
大力枚举 \(i,j\)。对于每个 \(i,j\) 都 \(O(n)\) 算,每次就是问在相邻两个数之间最少加多少个数。特别注意相邻两个数相同的情况。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=2000200,mod=998244353;
#define MP make_pair
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int n,ok[10][10][111],okk[10][10][10];
char s[maxn];
int main(){
scanf("%s",s+1);
n=strlen(s+1);
MEM(ok,0x3f);MEM(okk,0x3f);
FOR(i,0,9) FOR(j,0,9){
ok[i][j][0]=0;
FOR(l,0,99){
ok[i][j][l+i]=min(ok[i][j][l+i],ok[i][j][l]+1);
ok[i][j][l+j]=min(ok[i][j][l+j],ok[i][j][l]+1);
}
FOR(k,1,110) okk[i][j][k%10]=min(okk[i][j][k%10],ok[i][j][k]);
if(!i || !j) okk[i][j][0]=1;
// FOR(k,0,9) printf("ok[%d][%d][%d]=%d\n",i,j,k,ok[i][j][k]);
}
FOR(i,0,9){
FOR(j,0,9){
int ans=0;
bool flag=true;
FOR(k,2,n){
int x=okk[i][j][(s[k]-s[k-1]+10)%10];
x=max(x-1,0);
if(x>=1e9){printf("-1 ");flag=false;break;}
ans+=x;
}
if(flag) printf("%d ",ans);
}
puts("");
}
}
C
毒瘤玩意……当然可能是我写复杂了。
上下和左右互不干扰,分开考虑。以上下为例。
把上看成 \(1\),下看成 \(-1\),那么竖直方向一共跨过了最大前缀和-最小前缀和单位。
不妨枚举在哪里插入字符,然后瞎合并一通。
需要很多东西,比如每个前缀的后缀和的后缀最大值。(smg……)
不保证代码能让大家都理解。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=200020,mod=998244353;
#define MP make_pair
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int t,n,n1,n2,pre1[maxn],suf1[maxn],pre2[maxn],suf2[maxn];
int mnpre1[maxn],mxpre1[maxn],mnpre2[maxn],mxpre2[maxn],mnsuf1[maxn],mxsuf1[maxn],mnsuf2[maxn],mxsuf2[maxn];
int s1[maxn],s2[maxn];
ll ans;
char s[maxn];
void calc(int n,int a[],int pre[],int suf[],int mnpre[],int mxpre[],int mnsuf[],int mxsuf[]){
FOR(i,1,n) pre[i]=pre[i-1]+a[i];
ROF(i,n,1) suf[i]=suf[i+1]+a[i];
FOR(i,1,n) mnpre[i]=a[i]+min(0,mnpre[i-1]),mxpre[i]=a[i]+max(0,mxpre[i-1]);
ROF(i,n,1) mnsuf[i]=min(mnsuf[i+1],suf[i]),mxsuf[i]=max(mxsuf[i+1],suf[i]);
// FOR(i,1,n) printf("pre[%d]=%d,suf[%d]=%d,mnpre[%d]=%d,mxpre[%d]=%d,mnsuf[%d]=%d,mxsuf[%d]=%d\n",i,pre[i],i,suf[i],i,mnpre[i],i,mxpre[i],i,mnsuf[i],i,mxsuf[i]);
}
int main(){
t=read();
while(t--){
scanf("%s",s+1);
n=strlen(s+1);
n1=n2=0;
FOR(i,1,n){
if(s[i]=='W') s1[++n1]=1;
else if(s[i]=='S') s1[++n1]=-1;
else if(s[i]=='A') s2[++n2]=1;
else s2[++n2]=-1;
}
calc(n1,s1,pre1,suf1,mnpre1,mxpre1,mnsuf1,mxsuf1);
calc(n2,s2,pre2,suf2,mnpre2,mxpre2,mnsuf2,mxsuf2);
ans=1ll*(mxsuf2[1]-mnsuf2[1]+1)*(mxsuf1[1]-mnsuf1[1]+1);
// cout<<ans<<endl;
FOR(i,0,n1) ans=min(ans,1ll*(mxsuf2[1]-mnsuf2[1]+1)*(
min(
max(mxsuf1[i+1],suf1[i+1]+1+max(mxpre1[i],0))-min(mnsuf1[i+1],suf1[i+1]+1+min(mnpre1[i],0)),
max(mxsuf1[i+1],suf1[i+1]-1+max(mxpre1[i],0))-min(mnsuf1[i+1],suf1[i+1]-1+min(mnpre1[i],0))
)+1));
// cout<<ans<<endl;
FOR(i,0,n2) ans=min(ans,1ll*(mxsuf1[1]-mnsuf1[1]+1)*(
min(
max(mxsuf2[i+1],suf2[i+1]+1+max(mxpre2[i],0))-min(mnsuf2[i+1],suf2[i+1]+1+min(mnpre2[i],0)),
max(mxsuf2[i+1],suf2[i+1]-1+max(mxpre2[i],0))-min(mnsuf2[i+1],suf2[i+1]-1+min(mnpre2[i],0))
)+1));
cout<<ans<<endl;
FOR(i,0,n+1) pre1[i]=suf1[i]=pre2[i]=suf2[i]=mxpre1[i]=mnpre1[i]=mxsuf1[i]=mnsuf1[i]=mxpre2[i]=mnpre2[i]=mxsuf2[i]=mnsuf2[i]=0;
}
}
D
考虑只有一个 \(7\) 能不能做。\(7\) 明显在最右边。对于每个 \(1\),求出它右边有 \(x_i\) 个 \(3\),答案就是 \(\sum\frac{x_i(x_i-1)}{2}\)。
然后每次选一个尽可能大的 \(x_i\),不停构造,由于 \(x_i\) 肯定不超过 \(50000\),而且无论 \(n\) 多小都可以在后面加 \(2\) 个 \(3\) 使得 \(n\) 减少 \(1\),所以这组解一定存在且合法。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010,mod=998244353;
#define MP make_pair
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int t,n,a[maxn],k;
int main(){
t=read();
while(t--){
n=read();k=0;MEM(a,0);
while(n){
a[++k]=sqrt(2*n);
while(a[k]*(a[k]-1)<=2*n) a[k]++;
while(a[k]*(a[k]-1)>2*n) a[k]--;
n-=a[k]*(a[k]-1)/2;
}
FOR(i,1,k){
printf("1");
FOR(j,1,a[i]-a[i+1]) printf("3");
}
printf("7\n");
}
}
E
最小清新的一道题。
考虑求出 \(a[i]\) 表示在 \(t\) 中能以 \(i\) 结尾匹配的串的个数,\(b[i]\) 表示在 \(t\) 中能以 \(i\) 开头匹配的串的个数。答案是 \(\sum a[i]b[i+1]\)。
这两个东西都可以通过 AC 自动机简单求。大概就是维护 fail 链上末尾节点的个数之类的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=200020,mod=998244353;
#define MP make_pair
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
struct ACAM{
int cnt,ch[maxn][26],fail[maxn],q[maxn],sum[maxn],h,r,val[maxn];
void insert(char *s,int l){
int now=0;
FOR(i,1,l){
int p=s[i]-'a';
if(!ch[now][p]) ch[now][p]=++cnt;
now=ch[now][p];
}
sum[now]++;
}
void build(){
h=1;r=0;
FOR(i,0,25) if(ch[0][i]) q[++r]=ch[0][i];
while(h<=r){
int u=q[h++];
FOR(i,0,25) if(ch[u][i]){
fail[ch[u][i]]=ch[fail[u]][i];
sum[ch[u][i]]+=sum[fail[ch[u][i]]];
q[++r]=ch[u][i];
}
else ch[u][i]=ch[fail[u]][i];
}
}
void run(char *s,int l){
int now=0;
FOR(i,1,l){
int p=s[i]-'a';
now=ch[now][p];
val[i]=sum[now];
}
}
}AC[2];
int n,l;
ll ans;
char t[maxn],s[maxn];
int main(){
scanf("%s",t+1);l=strlen(t+1);
n=read();
FOR(i,1,n){
scanf("%s",s+1);
int len=strlen(s+1);
AC[0].insert(s,len);
for(int j=1,k=len;j<k;j++,k--) swap(s[j],s[k]);
AC[1].insert(s,len);
}
AC[0].build();AC[1].build();
AC[0].run(t,l);
for(int i=1,j=l;i<j;i++,j--) swap(t[i],t[j]);
AC[1].run(t,l);
FOR(i,1,l) ans+=1ll*AC[0].val[i]*AC[1].val[l-i];
// FOR(i,1,l) printf("val1[%d]=%d,val2[%d]=%d\n",i,AC[0].val[i],i,AC[1].val[l-i+1]);
cout<<ans<<endl;
}
Educational Codeforces Round 70 题解的更多相关文章
- Educational Codeforces Round 70 (Rated for Div. 2) 题解
比赛链接:https://codeforc.es/contest/1202 A. You Are Given Two Binary Strings... 题意:给出两个二进制数\(f(x)\)和\(f ...
- Educational Codeforces Round 19 题解【ABCDE】
A. k-Factorization 题意:给你一个n,问你这个数能否分割成k个大于1的数的乘积. 题解:因为n的取值范围很小,所以感觉dfs应该不会有很多种可能-- #include<bits ...
- Educational Codeforces Round 55 题解
题解 CF1082A [Vasya and Book] 史上最难A题,没有之一 从题意可以看出,翻到目标页只有三种办法 先从\(x\)到\(1\),再从\(1\)到\(y\) 先从\(x\)到\(n\ ...
- Codeforces Educational Codeforces Round 54 题解
题目链接:https://codeforc.es/contest/1076 A. Minimizing the String 题意:给出一个字符串,最多删掉一个字母,输出操作后字典序最小的字符串. 题 ...
- Codeforces Educational Codeforces Round 57 题解
传送门 Div 2的比赛,前四题还有那么多人过,应该是SB题,就不讲了. 这场比赛一堆计数题,很舒服.(虽然我没打) E. The Top Scorer 其实这题也不难,不知道为什么这么少人过. 考虑 ...
- Educational Codeforces Round 57题解
A.Find Divisible 沙比题 显然l和2*l可以直接满足条件. 代码 #include<iostream> #include<cctype> #include< ...
- Educational Codeforces Round 24 题解
A: 考你会不会除法 //By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long ...
- Educational Codeforces Round 70 (Rated for Div. 2)
这次真的好难...... 我这个绿名蒟蒻真的要崩溃了555... 我第二题就不会写...... 暴力搜索MLE得飞起. 好像用到最短路?然而我并没有学过,看来这个知识点又要学. 后面的题目赛中都没看, ...
- Educational Codeforces Round 70
目录 Contest Info Solutions A. You Are Given Two Binary Strings... B. You Are Given a Decimal String.. ...
随机推荐
- python asyncio as_completed
#asyncio 没有提供http协议的接口 aiohttp import asyncio import socket from urllib.parse import urlparse async ...
- CompletableFuture3
public class CompletableFuture3 { public static void main(String[] args) throws ExecutionException, ...
- 常用的排列、组合、阶乘函数 MATLAB
1.求n的阶乘,方法如下:a.factorial(n)b.gamma(n+1)c.v='n!'; vpa(v) 2.求组合(数),方法如下:a.combntns(x,m) 列举出从n个元素中取出 ...
- Devexpress treelist两张表父子节点设置、筛选、分页、排序、页面跳转demo
效果图 网上查了很多例子自己结合和修改了一下.最下方的分页跳转是dev的datapager控件.控件的属性事件自己研究一下. 代码如下 public partial class MMDefinitio ...
- SQL Server like 字段
参考资料:Cannot resolve the collation conflict between "Chinese_PRC_CI_AS" and "SQL_L及由于排 ...
- 进程调度算法spf,fpf,时间片轮转算法实现
调度的基本概念:从就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行,以实现进程并发地执行. 进程信息 struct node { string name;//进程名称 int id;//进程 ...
- deepin可视化程序打不开问题排查方法
anyconnect是一个VPN软件,在deepin系统下安装完成之后,并不能够直接使用,点击启动图标之后没有反应. 要想分析问题,必须从命令行入手,错误会打印在控制台. 如何根据一个图标来找到一个程 ...
- 用SignApk.jar对APK进行签名
对apk签名需要使用SignApk.jar和签名文件.可以使用Android源码获取,若没有源码,可以在这下载:SignApk.jar.(包含了SignApk.jar和签名文件和批处理文件) 1 Si ...
- 多个python版本共存时的pip配置
两种方法来配置pip Func1: 1.1 找到python环境的安装包,将python.exe文件重命名,如:将python2.7版本的python.exe重命名为Python2.exe,将pyth ...
- Java使用MD5加密算法,实现等登陆功能
Java实现MD5加密 为了保护有些数据,就需要采取一些手段来进行数据的加密,防止被别人破解. MD5简介 md5的全称是md5信息摘要算法(英文:MD5 Message-Digest Algorit ...