2024 暑假友谊赛 3

2024 暑假友谊赛 3

2024.8.3 9:00————12:00

过题数2/8
补题数4/8

  • CodeForces 1187E
  • CodeForces 977D
  • CodeForces 1368D
  • AtCoder arc082_b
  • CodeForces 794C
  • CodeForces 1076E
  • CodeForces 611D
  • CodeForces 1416B

B - Divide by three, multiply by two

题解:
有一个数字x,现在可以对它进行n-1次操作,既可以是把它除以3(必须是能整除的数字),也可以将它乘上2,现在打乱这些数字,给出打乱后的数字个数n和序列,请输出正确的顺序。
用一个双端队列,先找出最小值,先往左边找过去,能整除以2或能乘上3的数字,找到了就往左边放。然后往右边找,能乘上2或能整除以3的数字,就往右边放,最后输出即可。
代码:

#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>
#include<deque>

using namespace std;
#define int long long
#define endl "\n"
const int N = 110;
int a[N];
int n;
map<int,bool>mp;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    int mi = 3e18+10;
    for (int i = 1; i <= n; i++)  {
        cin >> a[i];
        mp[a[i]]= true;
        if(a[i] < mi)mi = a[i];
    }
    int cnt = 0;
    mp[mi] = false;
    deque<int>dq;
    dq.push_front(mi);
    int st = 0;
    int res = mi;
    while(dq.size() < n) {
        bool stt = false;
        if(mp[mi*3]) {
            dq.push_front(mi*3);
            mp[mi*3] = false;
            mi = mi*3;
            st = 3;
            stt = true;
        }
//        if(mp[mi*2]) {
//            dq.push_back(mi*2);
//            mp[mi*2] = false;
//            mi = mi*2;
//            st = 2;
//            stt = true;
//        }
//        if(mi%3 == 0) {
//            if(mp[mi/3]) {
//                dq.push_back(mi/3);
//                mp[mi/3] = false;
//                mi = mi/3;
//                st = 33;
//                stt = true;
//            }}
        if(mi % 2 == 0) {
            if(mp[mi/2]) {
                dq.push_front(mi/2);
                mp[mi/2] = false;
                mi = mi/2;
                st = 22;
                stt = true;
            }
        }
//        if(!stt) {
//            if(st == 2) mi = mi/2;
//            if(st == 3) mi = mi/3;
//            if(st == 22) mi = mi*2;
//            if(st == 33) mi = mi*3;
//        }
          if(!stt)break;
    }
    mi = res;
    while(dq.size() < n) {
        bool stt = false;
//        if(mp[mi*3]) {
//            dq.push_front(mi*3);
//            mp[mi*3] = false;
//            mi = mi*3;
//            st = 3;
//            stt = true;
//        }
        if(mp[mi*2]) {
            dq.push_back(mi*2);
            mp[mi*2] = false;
            mi = mi*2;
            st = 2;
            stt = true;
        }
        if(mi%3 == 0) {
            if(mp[mi/3]) {
                dq.push_back(mi/3);
                mp[mi/3] = false;
                mi = mi/3;
                st = 33;
                stt = true;
            }}
//        if(mi % 2 == 0) {
//            if(mp[mi/2]) {
//                dq.push_front(mi/2);
//                mp[mi/2] = false;
//                mi = mi/2;
//                st = 22;
//                stt = true;
//            }
//        }
//        if(!stt) {
//            if(st == 2) mi = mi/2;
//            if(st == 3) mi = mi/3;
//            if(st == 22) mi = mi*2;
//            if(st == 33) mi = mi*3;
//        }
          if(!stt)break;
    }
    while(!dq.empty()) {
        cout << dq.front() << ' ';
        dq.pop_front();
    }
    return 0;
}


D - Derangement

题解:
给出一个长度为n的序列p,序列中有1——n各个数字乱序,每次可以交换俩个相邻的数字,要求最后实现每个数字与位置不相等。
找找找,找到一个数字与序列相等的就记一个res,如果左右俩个数字都相等,它们俩可以相互交换,所以res-1,最后输出res即可。
代码:

#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>

using namespace std;
#define int long long
const int N = 1e5+10;
int n;
int p[N];

signed main() {
    cin >> n;
    int res = 0;
    for (int i = 1; i <= n; i++) {
        cin >> p[i];
        if(p[i] == i) {
            if(p[i-1] == i-1 && i-1 != 0) {
                swap(p[i-1],p[i]);
                res--;
            }
            res++;
        }
    }cout << res << endl;
    return 0;
}

E - Naming Company

题解:
给公司命名,Oleg手里有一个名字,希望使公司的名字尽可能的小,Igor的手中有一个名字,希望使公司的名字尽可能的大,从Oleg手中的名字开始,轮流取一个字母,放置在公司名字的某个位置,三串名字的长度相等。
先给俩人手中的字母进行排序,截取出俩个人手中打算放的字母,可以想象当Oleg此时要放置的字母比Lgor大的话,后面的字母全都会比它大,所以要把Oleg要放的最后一个字母尽量往后面放,因为要让越小的字母在越前面。
代码:

#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>
#include<deque>

using namespace std;
#define int long long
#define endl "\n"
const int N = 3e5+10;
char oleg[N],igor[N];
char an[N];
priority_queue<char>ig;
priority_queue<char,vector<char>,greater<char>>o;
string mi,ma;

signed main() {
    cin >> mi >> ma;
    int n = mi.length();
    int m = ma.length();
    for (int i = 0; i < mi.length(); i++) {
        oleg[i] = mi[i];
    }sort(oleg,oleg+n);
    for (int i = 0; i < ma.length(); i++) {
        igor[i] = ma[i];
    }sort(igor,igor+m,greater<char>());

    int cnt = 0;
    int res = n-1;
    for (int i = 0; i < n; i++)an[i] = '?';
    int qa1 = 0,qa2 = 0;
    int ho1 = (n+1)/2-1,ho2 = n/2-1;

    for (int i = 1; i <= n; i++) {
        if(i%2 == 1) {
            if(oleg[qa1] < igor[qa2]) an[cnt++] = oleg[qa1++];
            else an[res--] = oleg[ho1--];
        }
        else {
            if(oleg[qa1] < igor[qa2]) an[cnt++] = igor[qa2++];
            else an[res--] = igor[ho2--];
        }
    }

    for (int i = 0; i < n; i++)cout << an[i];
    return 0;
}

H - Make Them Equal

题解:
t组数据,每组数据有个序列长度为n的数组a,要求通过选取i,j,x,使a[i]=a[i]-xi,a[j]=a[j]+xi进行少于3*n次操作使得所有数字相等。输出操作次数以及相应的操作,不要求操作次数最少。
把所有的数字都给a[1]即可,无法完全给它的先借一点再给它,最后由1再还给大家。如果所有数字的总和无法整除,那么一定没有办法使所有数字相等,输出-1.
代码:

#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>
#include<deque>

using namespace std;
#define int long long
#define endl "\n"
const int N = 1e4+10;
int t;
int a[N];

struct ty {
    int p,q,x;
};

signed main() {
    cin >> t;
    while(t--) {
        int n;
        cin >> n;
        int sum= 0;
        vector<ty>an;
        for (int i = 1;i <= n; i++) {
            cin >> a[i];
            sum += a[i];
        }
        if(sum % n != 0) {
            cout << -1 << endl;
            continue;
        }
        sum/=n;
        for (int i = 2; i <= n; i++) {
//                int res = a[i]/i;
//                a[i] = a[i]%i;
// //               cout << i << ' ' << 1 << ' ' << res << endl;
//                an.push_back({i,1,res});
                if(a[i] % i != 0) {
                    int t = i-a[i]%i;
                    a[i] += t;
                    an.push_back({1,i,t});
                }
                an.push_back({i,1,a[i]/i});
        }
//        for (int i = 2; i <= n; i++) {
//            if(a[i] > sum) {
//                an.push_back({1,i,i-a[i]});
//                an.push_back({i,1,1});
//            }
//        }
        for (int i = 2; i <= n; i++) {
 //           cout << 1 << ' ' << i << ' ' << res << endl;
            an.push_back({1,i,sum});
        }
        cout << an.size() << endl;
        for (auto x : an) {
            cout << x.p << ' ' << x.q << ' ' << x.x << endl;
        }
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值