一.概况
比赛名称:Codeforces Round 895 (Div. 3)
日期:2023年10月28日 星期六
1.比赛过程
1.1 得分
A、B题A了,C题在本地就崩了,D题挂掉一个点,后面的没做。
1.2 赛时思路
A题很简单,只是个计算题。
B题想了一会儿,感觉有点思路,写了写,真对了。
C题一开始思路就想偏了。
D题想复杂了,写了一堆
i
f
−
e
l
s
e
if-else
if−else,结果WA了。
二.正解
A. Two Vessels
题意:有 a , b , c a,b,c a,b,c三个杯子,用 c c c杯子让 a , b a,b a,b中的水量相同。
思路:用 a a a和 b b b的差除以 c c c除以 2 2 2,再取上整即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
using namespace std;
double a,b,c;
int main(){
ll t;
cin>>t;
while(t--){
cin>>a>>b>>c;
ll x=ceil(abs(a-b)/2/c);
cout<<x;pr;
}
return 0;
}
B. The Corridor or There and Back Again
题意:有若干个房间排成一行,其中有 n n n个房间有陷阱,对于这 n n n个房间,它们有两个属性: d i d_i di和 s i s_i si,分别代表标号和陷阱形成的时间,即若你第 t t t秒第一次到达 i i i号房间, t + s i t+s_i t+si秒时陷阱就会在此房间形成,此后你无法通过此房间。每秒你可以走到与当前房间标号相邻的房间。你需要从 1 1 1号房间走到 k k k号房间,并且再从 k k k号房间走回 1 1 1号房间。求 k k k最大是多少。
思路:通过枚举找最小值,其中:
m
i
n
n
=
m
i
n
{
m
i
n
n
d
+
(
s
+
1
)
/
2
−
1
minn=min\left\{\begin{matrix}minn\\d+(s+1)/2-1\end{matrix}\right.
minn=min{minnd+(s+1)/2−1
代码:
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
int main(){
ll t;
cin>>t;
while(t--){
ll n;
cin>>n;
ll minn=INF;
while(n--){
ll d,s;
cin>>d>>s;
minn=min(minn,d+(s+1)/2-1);
}
cout<<minn;pr;
}
return 0;
}
C. Non-coprime Split
题意:给出
l
,
r
l,r
l,r,构造一组
a
,
b
a,b
a,b 使满足以下条件:
l
≤
a
+
b
≤
r
l \le a+b \le r
l≤a+b≤r
gcd
(
a
,
b
)
≠
1
\gcd(a,b) \neq 1
gcd(a,b)=1
若有多组解,则输出任意一组。
若无解,则输出
−
1
-1
−1。
思路:两种情况:
1 区间长度>2,构造
(
x
−
2
,
2
)
(x-2,2)
(x−2,2)的组合,输出。
2 区间长度为1,找到除本身以外的x的某个质因子k,则此时必然有
gcd
(
x
−
k
,
k
)
=
k
\gcd(x-k,k)=k
gcd(x−k,k)=k,输出
x
−
k
x-k
x−k和
k
k
k即可。否则输出
−
1
-1
−1
代码:
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define no printf("-1");pr;
using namespace std;
ll p(ll n){
for(int i=2;i*i<=n;i++){
if(n%i==0){
return i;
}
}
return 0;
}
int main(){
ll t;
cin>>t;
bool flag=0;
while(t--){
ll l,r;
cin>>l>>r;
flag=0;
for(int i=l;i<=r;i++){
ll t=p(i);
if(t!=0){
cout<<t<<" "<<i-t;pr;
flag=1;
break;
}
}
if(flag!=1){
no;
}
}
return 0;
}
D. Plus Minus Permutation
题意:
给定三个整数
n
,
x
,
y
(
1
≤
n
≤
1
0
9
,
1
≤
x
,
y
≤
n
)
n,x,y(1 \le n \le 10^9, 1 \le x, y \le n)
n,x,y(1≤n≤109,1≤x,y≤n),对于
n
n
n 的排列
p
p
p,有
s
c
o
r
e
(
p
)
=
(
p
x
+
p
2
x
+
p
3
x
+
…
+
p
⌊
n
x
⌋
⋅
x
)
−
(
p
y
+
p
2
y
+
…
+
p
⌊
n
y
⌋
⋅
y
)
score(p)=(p_x+p_{2x}+p_{3x}+ \ldots +p_{\lfloor \frac{n}{x}\rfloor \cdot x}) - (p_{y} + p_{2y} + \ldots + p_{\lfloor \frac{n}{y} \rfloor \cdot y})
score(p)=(px+p2x+p3x+…+p⌊xn⌋⋅x)−(py+p2y+…+p⌊yn⌋⋅y)。
求可能的最大
s
c
o
r
e
score
score。
思路:简单的贪心。 p x p_x px尽量大, P y P_y Py尽量小。
代码:
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
ll n,x,y;
ll lcm(ll x,ll y){
return x/__gcd(x,y)*y;
}
ll sum(ll x,ll y,ll k){
return (x+y)*k/2;
}
void solve(){
cin>>n>>x>>y;
ll cx=n/x,cy=n/y,cz=n/lcm(x,y);
cx-=cz;
cy-=cz;
cout<<sum(n-cx+1,n,cx)-sum(1,cy,cy);pr;
}
int main(){
ll t;
cin>>t;
while(t--){
solve();
}
}
E. Data Structures Fan
题意:给定一个长度为 n n n 的数组和一个长度为 n n n 的二进制串 s s s,现有两个操作:
1 l r
,表示将 l ≤ i ≤ r l \le i \le r l≤i≤r 的所有 s i s_i si 取反( 0 0 0 变 1 1 1, 1 1 1 变 0 0 0);2 g
( g ∈ { 0 , 1 } ) (g\in \{0,1\}) (g∈{0,1}),表示将所有 s i = g s_i=g si=g 的 a i a_i ai 求异或和;
1 ≤ n ≤ 1 0 5 , 1 ≤ t ≤ 1 0 4 1\le n\le 10^5,1\le t\le 10^4 1≤n≤105,1≤t≤104.
思路:分别记录数字 0 0 0和 1 1 1对应的总的异或和。修改操作将两个异或和分别与区间异或和异或就能得到翻转后的答案,查询操作直接输出对应答案即可。用异或前缀和优化。
代码:
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
using namespace std;
ll t,n,a[100005],q,ans[2],c[100005];
char str[100005];
int main(){
scanf("%lld",&t);
while(t--){
for(int i=1;i<=n;i++){
c[i]=0;
}
ans[0]=ans[1]=0;
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",a+i);
}
cin>>str+1;
for(int i=1;i<=n;i++){
ans[str[i]-'0']^=a[i];
c[i]=c[i-1]^a[i];
}
scanf("%lld",&q);
while(q--){
ll op;
scanf("%lld",&op);
if(op&1){
ll l,r;
scanf("%lld%lld",&l,&r);
ans[0]^=c[r]^c[l-1];
ans[1]^=c[r]^c[l-1];
}
else{
ll x;
scanf("%lld",&x);
printf("%lld ",ans[x]);
}
}
pr;
}
return 0;
}
F. Selling a Menagerie
题意:动物园里有
n
n
n 个动物,第
i
i
i 个动物害怕第
a
i
a_i
ai 个动物,第
i
i
i 个动物价值
c
i
c_i
ci 元。现在我要将这些动物全部卖掉。显然,卖掉的动物编号可以构成一个排列
p
p
p。
考虑卖掉这些动物时:
- 若 a i a_i ai 在 i i i 还没有卖掉之前就被卖掉了,现在卖掉 i i i,可以获得 c i c_i ci 元;
- 若 a i a_i ai 在 i i i 还没有卖掉之前没被卖掉,现在卖掉 i i i,可以获得 2 ⋅ c i 2·c_i 2⋅ci 元;
构造并输出赚钱最多的动物卖出顺序。
思路:贪心,假设第 x x x个动物可以吃掉的动物价格总和为 s u m sum sum,优先卖掉 s u m sum sum小的动物。
代码:
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
using namespace std;
const ll N=1e5+5;
ll n;
ll a[N],sum[N],c[N];
//价格sum
priority_queue<pair<ll,ll>,vector<pair<ll,ll> >,greater<pair<ll,ll> > > q;
bool st[N];
void slove(){
//假设第x个动物可以吃掉的动物价格总和为sum,优先卖掉sum小的动物
memset(a,0,sizeof a);memset(c,0,sizeof c);memset(st,0,sizeof st);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>c[i];
sum[a[i]]+=c[i];
}
for(int i=1;i<=n;i++){
q.push(make_pair(sum[i],i));
}
while(!q.empty()){
int t=q.top().second;
q.pop();
if(st[t]){
continue;
}
st[t]=1;
cout<<t<<" ";
sum[a[t]]-=c[t];
q.push(make_pair(sum[a[t]],a[t]));
}
}
int main(){
int t;
cin>>t;
while(t--){
slove();pr;
}
return 0;
}
三.总结
第一次打codeforces比赛,终于知道为什么有些人写的代码主函数里只有solve了,真好用:)
一开始提交代码时没管"语言",一直CE,后来才调过来……