【ABC 313】A~E题解

好久没打过比赛了,也好久没写过题解。cf时间有点阴间,来做下ABC

这次做出了A~D,rk900+,E感觉赛时过的和D人数差不多,但我不是很会数数(哭

A

A - To Be Saikyo

题意:给你 n 个数 Pi,找到最小的非负整数 x 使得 P1+x>Pi

做法:x=max(x,PiP1+1) 循环一遍即可。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 100 + 10, M = 2e6 + 10, mod = 100003;
int n, a[N];

int main(){
    ios::sync_with_stdio(false);
    cin >> n;
    int x = 0;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
        if(i > 1) {
            x = max(x, a[i] - a[1] + 1);
        }
    }
    cout << x << endl;
	return 0;
} 

B

B - Who is Saikyo?

题意:有 n(n<=50) 个人,m 对关系,每对关系 (x,y) 表示 x 能力强于 y,这种关系具有传递性。问谁是最强的,如果不能唯一确定,输出-1

做法:

  1. 有点复杂,我的做法是floyd,求出每两个人之间的关系
点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 100 + 10, M = 2e6 + 10, mod = 100003;
int n, m, a[N];
int g[N][N];

int floyd() {
    for(int k = 1; k <= n; k++) {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                if(g[i][k] && g[k][j]) {
                    g[i][j] = 1;
                }
            }
        }
    }
    // for(int i = 1; i <= n; i++) {
    //     for(int j = 1; j <= n; j++) {
    //         if(i == j)continue;
    //         if(g[i][j] && g[j][i]) return -1;
    //     }
    // }
    for(int k = 1; k <= n; k++) {
        bool f = 1;
        for(int i = 1; i <= n; i++) {
            if(g[k][i] || i == k) continue;
            else {f = 0; break;}
        }
        if(f) return k; 
    }
    return -1;
}

int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for(int i = 1, x, y; i <= m; i++) {
        cin >> x >> y;
        g[x][y] = 1;
    }
    cout << floyd() << endl;
	return 0;
} 

  1. x 强于 y 抽象成 xy 有一条有向边,这样可以知道,最强的人就是度数为0的点,假设这样的点只有一个,那么就是答案
点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 100 + 10, M = 2e6 + 10, mod = 100003;
int n, m, a[N];
int rd[N];

int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for(int i = 1, x, y; i <= m; i++) {
        cin >> x >> y;
        rd[y]++;
    }
    int cnt = 0, ans;
    for(int i = 1; i <= n; i++) {
        if(!rd[i]) cnt++, ans = i;
    }
    if(cnt != 1) ans = -1;
    cout << ans << endl;
	return 0;
} 

C

C - Approximate Equalization 2

题意:给你 n(n<=2105) 个数,定义一次操作为一个数+=1,一个数-=1,问你最少需要多少次操作,能把整个数列变成最大值与最小值的差不超过1

做法:可以求出 ave=ain,改变后值为 ave+1 的有 more=aiaven 个,值为 ave 的有 nmore 个。将 ai 排序,最后肯定是前 nmore 个值为 ave, 后 more 个值为 ave+1。因为序列增加的值的和与减小的值的和相等,让我们只看应该增大值的 ai,如果 ai 小于它应该成为的值,就把 supposed(ai)ai 加进答案。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10;
ll n, m, a[N];

int main(){
    ios::sync_with_stdio(false);
    cin >> n;
    ll tot = 0;
    for(int i = 1, x, y; i <= n; i++) {
        cin >> a[i];
        tot += a[i];
    }
    sort(a + 1, a + n + 1);
    ll ave = tot / n;
    ll ans = 0, more = tot - ave * n;
    if(more == 0) {
        for(int i = 1, x, y; i <= n; i++) {
            if(a[i] < ave) ans += ave - a[i];
        }
    }
    else {
        // more 个 ave+1, n-more 个 ave
        for(int i = 1; i <= n - more; i++) {
            if(a[i] < ave) ans += ave - a[i];
            else break;
        }
        for(int i = n - more + 1; i <= n; i++) {
            if(a[i] < ave + 1) ans += ave + 1 - a[i];
        }
    }
    cout << ans << endl;
	return 0;
} 

D

D - Odd or Even

题意:交互题。有 n(n<=1000) 个数,它们的值是0或者1,每次可以询问 k(k<n,k) 个数的和是奇数还是偶数, 最多问 n 次。求这 n 个数的值。

做法:
首先问 base = 【1,2,3,...,k-1,k】
然后依次问 tem =【1,2,3,...,k-1,i】 ... (i的值从k+1取到n),共 nk+1 次。可以知道k+1 到 n 这些数和 ak 的值相同或不同。

之后,问【1,2,3,...,k+1,k】、【1,2,3,...,k+1,k-1,k】...(把k+1插入k-1、k-2、... 1的位置,其他数和base保持一致),共 k1 次,可以知道 1 到 k-1 这些数和 ak+1 的值相同或不同。

总共就问了 n 次。

这样就把所有数划分为两个阵营,一个阵营的数值全为0,另一个全为1。

然后根据base的值,它由 k 个数的和组成,而 k 为奇数,所以根据这k个数包含奇数个1,偶数个0(和为奇数),或者偶数个1、奇数个0(和为偶数)的关系,就可以知道每个阵营的数的值。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1005 + 10;
int n, k;
int ans[N], result[N];
int base, tem, rec;
set<int> st[2];

inline int ask() {
    int res;
    cout << '?';
    for(int i = 1; i <= k; i++) {
        cout << ' ' << ans[i];
    }cout << endl;
    cin >> res;
    return res;
}

void solve() {
    for(int i = 1; i <= k; i++) ans[i] = i;
    base = ask();  // 1 to k

    st[0].insert(k);
    for(int i = k + 1; i <= n; i++) {
        ans[k] = i;
        tem = ask();
        if(tem == base) {
            st[0].insert(i);
            if(i == k + 1) rec = 0;
        }
        else {
            st[1].insert(i);
            if(i == k + 1) rec = 1;
        }
    }
    ans[k] = k;

    for(int i = k - 1; i >= 1; i--) {
        ans[i] = k + 1;
        tem = ask();
        if(tem == base) st[rec].insert(i);
        else st[1 - rec].insert(i);

        ans[i] = i;
    }

    int cnt = 0;
    for(int i = 1; i <= k; i++) {
        if(st[0].count(i) == 1) cnt++;
    }
    cnt %= 2;
    if(cnt == base) {
        //k=1
        for(auto x : st[0]) result[x] = 1;
    }
    else {
        //k=0
        for(auto x : st[1]) result[x] = 1;
    }
    
    cout << '!';
    for(int i = 1; i <= n; i++) cout << ' ' << result[i];
    cout << endl;
}

int main(){
    cin >> n >> k;
    solve();
	return 0;
} 

E

这题是赛后补的

E - Duplicate

给你一个数字串s(包含1到9),一次操作可以让 si 变成 si+1si,最后一个字符去掉。问多少次操作可以让s变成长度为1,如果不可能,输出-1

做法:容易发现如果出现两个连续的非1数字,答案为-1

我们要求的是操作的次数,记为ans。

如果最后一个数是1,那么ans+=1
否则,ans+=1+(s[i]1)(ans+1)

理解:ans += 1,是删掉当前这个数的操作次数;非1的数x每次操作会增长x-1个1,此前已经操作了ans次,那么一个非1的数y总共增加 (x-1)(ans)次,又因为删掉当前这个数又会导致一次1数量的增长,所以ans+=(x-1)(ans+1)

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1005 + 10;
int n;
string s;

int main(){
    cin >> n >> s;
    for(int i = 0; i < s.length(); i++) {
        if(i && s[i] != '1' && s[i - 1] != '1') {
            cout << -1 << endl;
            return 0;
        } 
    }
    ll ans = 0;
    while(1) {
        while(s.length() > 1 && s.back() == '1') s.pop_back(), ans++;
        if(s.length() == 1) {cout << ans << endl; return 0;}
        int tem = s.back() - '0'; s.pop_back();
        ans += 1 + (tem - 1) * (ans + 1) % 998244353;
        ans %= 998244353;
    }
    cout << ans << endl;

	return 0;
} 

posted @   starlightlmy  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示