Educational Codeforces Round 151 (Rated for Div. 2)
A.Forbidden Integer
题意
给你一个整数 n n n,你想要得到它。从 1 1 1 到 k k k 的每一个整数都有无限的供应,除了整数 x x x(根本没有整数 x x x)。你可以取任意数量的这些整数(可能是零)。你能使所取整数的和等于 n n n 吗?如果有多个答案,打印其中任何一个。
解题思路
首先发现如果 x ! = 1 x!=1 x!=1,那么一定有解,就是 n n n 个 1 1 1,否则就是 x = = 1 x==1 x==1,才可能无解,如果 k > 2 k>2 k>2 这时候我们贪心的使用尽可能多的 2 2 2,并且剩下的数不能是 1 1 1,如果 n n n 是偶数,那么就是 n / 2 n/2 n/2 个 2 2 2,否则就是 n / 2 − 1 n/2-1 n/2−1 个 2 2 2 加上一个 3 3 3,如果这时候取不到 3 3 3,那么就是无解。
AC_Code
//
// Created by 24624 on 2023/6/29.
//
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k,x;
cin>>n>>k>>x;
if(x!=1)
{
cout<<"YES"<<endl;
cout<<n<<endl;
for(int i=1;i<=n;i++)
{
cout<<1<<' ';
}
cout<<endl;
continue;
}
else
{
int flag=0;
for(int i=2;i<=k;i++)
{
if(n%i+i<=k)
{
cout<<"YES"<<endl;
cout<<n/i-1+1<<endl;
for(int j=1;j<=n/i-1;j++)
{
cout<<i<<' ';
}
cout<<n%i+i<<endl;
flag=1;
break;
}
}
if(flag)continue;
}
cout<<"NO"<<endl;
}
return 0;
}
B.Come Together
题意
鲍勃和卡罗尔和爱丽丝玩了一整天,现在该回家了。爱丽丝、鲍勃和卡罗尔分别生活在无限的二维网格 A , B A,B A,B 和 C C C 单元格中。现在,它们都在 A A A 单元格里。如果 Bob (或 Carol )在某个单元格中,他(她)可以移动到邻近的单元格之一。如果两个细胞共用一条边,就称为相邻细胞。例如,单元格 ( 3 , 5 ) (3,5) (3,5) 有四个相邻的单元格: ( 2 , 5 ) 、 ( 4 , 5 ) 、 ( 3 , 6 ) (2,5)、(4,5)、(3,6) (2,5)、(4,5)、(3,6) 和 ( 3 , 4 ) ( 3,4) (3,4)。鲍勃想回到单元格 B B B,卡罗尔,回到单元格 C C C。它们都想走最短的路径,也就是说,走由尽可能少的细胞组成的路径。但他们也想一起走。如果鲍勃和卡罗尔各自走一条最短的路径回家,他们可以一起走的最大细胞数是多少?
解题思路
可以分为两种相同路径的情况,一种是一条直的路径,一种是拐弯了的路径,这两种路径可以用 b , c b,c b,c 点横纵坐标到 a a a 点的距离表示。
并且可以通过这个符号类型依据分出这两种情况,剩下的就是路径长度为 1 1 1。
AC_Code
#include<iostream>
using namespace std;
#define int long long
signed main()
{
int t;
cin>>t;
while(t--)
{
int ax,ay,bx,by,cx,cy;
cin>> ax>> ay>> bx>> by>> cx>> cy;
int dbx=bx-ax;
int dby=by-ay;
int dcx=cx-ax;
int dcy=cy-ay;
if(dbx*dcx<=0&&dby*dcy>0)
{
cout<<min(abs(dby),abs(dcy))+1<<endl;
}
else if(dbx*dcx>0&&dby*dcy<=0)
{
cout<<min(abs(dbx),abs(dcx))+1<<endl;
}
else if(dbx*dcx>0&&dby*dcy>0)
{
cout<<min(abs(dbx),abs(dcx))+min(abs(dby),abs(dcy))+1<<endl;
}
else cout<<1<<endl;
}
return 0;
}
C.Strong Password
题意
Monocarp 终于鼓起勇气在 ForceCoders 上注册了。他想出了一个手柄,但还在考虑密码。他希望自己的密码越强越好,所以他提出了以下标准:密码的长度应该正好是 m m m;密码只能由 0 0 0 到 9 9 9 的数字组成;密码不应该以子序列(不一定是连续的)的形式出现在密码数据库中(以字符串 s s s 的形式给出)。Monocarp 还提出了两个长度为 m m m 的字符串: l l l 和 r r r,它们都只由 0 0 0 到 9 9 9 的数字组成。他希望他的密码的第 i i i 位在 l i l_i li 和 r i r_i ri 之间,包括 l i l_i li 和 r i r_i ri。是否存在一个符合所有条件的密码?
解题思路
我们可以考虑寻找一个最有可能成为答案的密码,最有可能成为答案的密码的元素在密码库中的位置一定是比较靠后的,因为越靠后,这个密码成为子序列的概率就越低,所以我们尝试在密码库中比对,遍历l,r,每次选择一个在密码库中最靠后的元素,当然了,我们需要选的是这个元素的第一个下标,不选择第一个就不能保证前面不会产生子序列,怎么快速的选最小的呢,我们可以使用一个数组维护最小的下标。
AC_Code
#include<iostream>
#include<string>
#include<vector>
#include<unordered_map>
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)
{
string s;
cin>>s;
int m;
cin>>m;
string l,r;
cin>>l>>r;
int flag=0;
vector<vector<int>>mp(s.size()+2,vector<int>(12,s.size()+1));
for(int i=s.size()-1;i>=0;i--)
{ mp[i]=mp[i+1];
mp[i][s[i]-'0']=i;
}
for(int i=0,k=0;i<m;i++)
{
int x=0;
for(int j=l[i]-'0';j<=r[i]-'0';j++)
{
x=max(mp[k][j],x);
}
k=x+1;
if(x>=s.size())
{
flag=1;
break;
}
}
if(!flag)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
D.Rating System
题意
您正在为一款在线游戏开发一个评级系统。每次玩家参加比赛时,玩家的评级都会根据结果而改变。最初,玩家的评分是 0 0 0。有 n n n 个匹配;在第 i i i 场比赛之后,评分变化等于 a i a_i ai(如果 a i a_i ai 为正,评分增加 a i a_i ai;如果 a i a_i ai 为负,评分减少 a i a_i ai)。序列 a a a 中没有零。这个系统还有一个额外的规则:对于一个固定的整数 k k k,如果玩家的评分达到 k k k,它就永远不会低于 k k k。正式地说,如果玩家的评级至少为 k k k,而评级改变将使其低于 k k k,那么评级将降至 k k k。你的任务是确定 k k k 的值,使玩家在所有 n n n 场比赛后的评分是可能的最大值(在所有 k k k 的整数值中)。如果有多个可能的答案,您可以打印其中的任何一个。
解题思路
先求个前缀和 b b b,用一个数组 s s s 维护后 i i i 个数的前缀和数组中的最小值,原数组为 a a a,那么我们再贪心的用一个变量维护从前往后的前缀和最大值,只要更新了最大值,就可以尝试更新答案。答案 a n s ans ans 初始化为当 k = 0 k=0 k=0 时的结果,所以更新时应该为 a n s = max ( a n s , b [ n ] + ( max ( 1 l l ∗ 0 , b [ i ] − s [ i ] ) ) ) ans=\max(ans,b[n]+(\max(1ll*0,b[i]-s[i]))) ans=max(ans,b[n]+(max(1ll∗0,b[i]−s[i]))),这里会爆 i n t int int,需要开 l o n g l o n g long\ long long long。
AC_Code
#include<iostream>
#include<vector>
using namespace std;
#define int long long
signed main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
vector<int>a(n+1,0),b(n+1,0),c(n+1,0);
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=b[i-1]+a[i];
}
int ans=0;
int maxx=0;
vector<int>s(n+1);
s[n]=b[n];
for(int i=n;i>=1;i--)
{
if(i!=n)s[i]=min(s[i+1],b[i]);
}
int k=0;
ans=max(1ll*0,b[0]-s[1])+b[n];
for(int i=1;i<=n;i++)
{
if(b[i]>maxx)
{
if(ans<b[n]+(max(1ll*0,b[i]-s[i])))
{
ans=b[n]+(max(1ll*0,b[i]-s[i]));
maxx=b[i];
k=b[i];
}
}
}
cout<<k<<endl;
}
return 0;
}