Codeforces Round 895 (Div. 3)补题报告

目录

链接

一、题目报告

二、赛中状况

三、解题报告

A.Two Vessels

题目大意

题目解析

正解代码

B.The Corridor or There and Back Again

题目大意

题目解析

正解代码

C.Non-coprime Split

题目大意

题目解析

正解代码

D.Plus Minus Permutation

题目大意

题目解析

正解代码

E.Data Structures Fan

题目大意

题目解析

正解代码

F.Selling a Menagerie

题目大意

题目解析

正解代码

四、总结


链接

Dashboard - Codeforces Round 895 (Div. 3) - CodeforcesCodeforces. Programming competitions and contests, programming communityicon-default.png?t=N7T8https://codeforces.com/contest/1872

一、题目报告

比赛时,做出来了A-D题。比赛后,通过老师讲解完成了A-E题。

二、赛中状况

A题,非常轻松的水掉了。

B题,也非常的简单,但是我因为数组大小开的过小“蛙”掉了一次,悲!

C题,难度也不高,但是因为一些特殊的细节处理不到位,“蛙”了两次,悲上加悲!

D题,一道非常so easy的数学题啊,水掉了。

至于E-G题吗,老师说了,难度有点高,不做了!!!

三、解题报告

A.Two Vessels

题目大意

有分别装有a,b单位水的两个杯子,容量无限大。现在有一个勺子,容量为 c,每次可以从一个杯子里舀一勺不超过c单位的水(c可以不是整数),放入另一个杯子中。请问最少需要多少次操作才能使两个杯子里的水量相同。

题目解析

非常简单的一道数学题啊!只需要计算出a,b两个杯子之间水量的差,除以2,再去除以c去上取整就能得到答案,注意是多组输入!!!

正解代码

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <list>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod) - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

#define N 10005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007

// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
//     ll x;
//     ll y;
// }d[N];

int main() {
    // file("")
    // CLOSE
    ll t;
    cin>>t;
    while(t--){
        ll n,m,k;
        cin>>n>>m>>k;
        ll dd=labs(n-m)/2.0+0.5;
        ll ans=dd/k+(dd%k!=0?1:0);
        cout<<ans<<endl;
    }
    return 0;
}

B.The Corridor or There and Back Again

题目大意

有若干个房间组成一排,给你n个有陷阱的房间,每个房间都有编号和陷阱爆炸时间,你必须在陷阱爆炸之前回到这个房间,问你能走到最远的房间是哪。

题目解析

因为通过计算可知你最多可以进入299号房间,所以可以判断每一个房间可以到达的最远的房间号全部之中最小值,即可求出答案。

正解代码

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <list>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod) - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

#define N 10005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007

// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
//     ll x;
//     ll y;
// }d[N];

int main() {
    // file("")
    // CLOSE
    ll t;
    cin>>t;
    while(t--){
        ll n;
        ll a[1005];
        mem(a,0x3f);
        cin>>n;
        for(ll i=1;i<=n;i++){
            ll x,y;
            cin>>x>>y;
            a[x]=min(a[x],y);
        }
        ll k=1000;
        ll i=1;
        while(i<=k){
            if(a[i]<=200){
                k=min(i+(a[i]-1)/2,k);
            }
            i++;
        }
        cout<<k<<endl;
    }
    return 0;
}

C.Non-coprime Split

题目大意

给出l,r,构造一组a,b使满足以下条件:

  • l\leqslant a+b\leqslant r
  • gcd(a,b)\neq 1

若有多组解,则输出任意一组。

题目解析

简单推理可知,当区间小于等于3时无解,否则当区间长度大于2时,解为区间内的一个偶数的一半m\rightarrow (m,m),当区间长度为1时,可以判断,这个数不是质数,可以去找一对分解出来的数m,n\to (n,m*n-n),这个数是质数是,无解。

正解代码

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <list>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod) - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

#define N 10005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007

// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
//     ll x;
//     ll y;
// }d[N];

int main() {
    // file("")
    // CLOSE
    ll t;
    cin>>t;
    while(t--){
        ll l,r;
        cin>>l>>r;
        if(l<3)l=3;
        if(l>r)cout<<-1<<endl;
        else{
            if(r-l+1>=2){
                while(l&1)l++;
                cout<<l/2<<' '<<l/2<<endl;
            }
            else{
                bool flag=0;
                for(ll i=2;i*i<=r;i++){
                    if(r%i==0){
                        cout<<r/i<<' '<<(i-1)*r/i<<endl;
                        flag=1;
                        break;
                    }
                }
                if(!flag)cout<<-1<<endl;
            }
        }
    }
    return 0;
}

D.Plus Minus Permutation

题目大意

给定三个整数 n,x,y,对于 n 的排列p,有score(p)=(p_{x},p_{2x},p_{3x},...,p_{\left \lfloor \frac{n}{x} \right \rfloor*x})+(p_{y},p_{2y},p_{3y},...,p_{\left \lfloor \frac{n}{y} \right \rfloor*y})
求可能的最大score

题目解析

数学题,可以先计算出能取出多少个与p_{ky}重合的p_{kx},在计算取出多少个与p_{kx}重合的p_{ky},利用等差序列公式求解最大值即可。

正解代码

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <list>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod) - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

#define N 10005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007

// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
//     ll x;
//     ll y;
// }d[N];

int main() {
    // file("")
    // CLOSE
    ll t;
    cin>>t;
    while(t--){
        ll n,m,l;
        cin>>n>>m>>l;
        ll alen=n/m-n/(m*l/gcd(m,l));
        ll blen=n/l-n/(m*l/gcd(m,l));
        ll ans=((n+(n-alen+1))*alen/2)-((1+blen)*blen)/2;
        cout<<ans<<endl;
    }
    return 0;
}

E.Data Structures Fan

题目大意

给定一个长度为n的数组和一个长度为n的二进制串s现有两个操作:

  1. 1 l r,表示将l-r区间内的所有s_i取反(0 变 1,1 变 0)
  2. 2 g,表示将所有s_{i}=ga_{i}求异或和

题目解析

本题可以使用前缀和做。

在执行所有操作前,先把所有的前缀异或和求出,并且求出s_{i}=0s_{i}=1的异或和。

1.取反操作 可以直接让s0s1异或上l-r区间内的前缀和。

2.求和操作 直接输出对应的s0s1即可

正解代码

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <list>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod) - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

#define N 100005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007

// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
//     ll x;
//     ll y;
// }d[N];
ll a[N];
ll sum[N];
int main() {
    // file("")
    // CLOSE
    ll t;
    cin>>t;
    while(t--){
        ll n;
        cin>>n;
        ll i;
        rep(i,1,n)cin>>a[i];
        string s;
        cin>>s;
        ll q;
        cin>>q;
        ll ans1=0,ans0=0;
        mem(sum,0);
        for(int i=0;i<n;i++){
            if(s[i]=='1')ans1^=a[i+1];
            else ans0^=a[i+1];
            sum[i+1]=sum[i]^a[i+1];
        }
        while(q--){
            ll opt;
            cin>>opt;
            if(opt==1){
                ll l,r;
                cin>>l>>r;
                ans0^=(sum[r]^sum[l-1]);
                ans1^=(sum[r]^sum[l-1]);
            }
            else{
                char x;
                cin>>x;
                if(x=='0')cout<<ans0<<' ';
                else cout<<ans1<<' ';
            }
        }
        enter
    }
    return 0;
}

F.Selling a Menagerie

题目大意

动物园里有n个动物,第i个动物害怕第a_i个动物,第i个动物价值c_i元。现在我要将这些动物全部卖掉。显然,卖掉的动物编号可以构成一个排列p

考虑卖掉这些动物时:

  1. a_ii还没有卖掉之前就被卖掉了,现在卖掉i,可以获得c_i元;
  2. a_ii还没有卖掉之前没被卖掉,现在卖掉i,可以获得2*c_i元;

构造并输出赚钱最多的动物卖出顺序。

题目解析

既然要求最大值,肯定每次卖出的动物之前没有他害怕的动物最好,所以可以根据他害怕的动物构成一个拓扑数列,每次从中取出没有入的点,肯定最优。

但是这会有个问题,可能会出现一个或者多个环的情况,只需要找到次环中最小值的害怕动物最先取出,后面依次取出即可。

正解代码

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <list>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod) - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

#define N 100005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007

// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
//     ll x;
//     ll y;
// }d[N];
ll a[N],c[N];
ll ru[N];
ll n,i,num;
queue<ll> q;

void huan(ll x){
    ll id=x,u=x;
    while(a[u]!=x){
        u=a[u];
        if(c[id]>c[u])id=u;
    }
    u=a[id];
    while(u!=id){
        cout<<u<<' ';
        ru[u]--;
        u=a[u];
    }
    ru[id]--;
    cout<<id<<' ';
}
void tuopo(){
    rep(i,1,n)if(ru[i]==0)q.push(i);
    while(!q.empty()){
        ll u=q.front();
        q.pop();
        cout<<u<<' ';
        num--;
        ru[a[u]]--;
        if(ru[a[u]]==0)q.push(a[u]);
    }
    if(num){
        rep(i,1,n){
            if(ru[i]!=0){
                huan(i);
            }
        }
    }
}
int main() {
    // file("")
    // CLOSE
    ll t;
    cin>>t;
    while(t--){
        cin>>n;
        num=n;
        mem(ru,0);
        rep(i,1,n){cin>>a[i];ru[a[i]]++;}
        c[0]=inf;
        rep(i,1,n)cin>>c[i];
        tuopo();
        enter
    }
    return 0;
}

四、总结

本次比赛我并没有完成后三道题目,我觉得不应该,再下一次考试中,我应该更加努力,争取AK!!!

2023.11.4 22:43完成

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值