Educational Codeforces Round 122 (Rated for Div. 2)——A~D

本文分享了三道编程竞赛中的题目及其解题思路。A题要求找到一个整数,通过改变一位使其能被7整除;B题考察处理01字符串,找出最少删除数使0和1数量相等的最长子串;C题涉及角色血量与攻击力的计算,决定是否能击败怪物;D题是关于数组操作和01背包问题,求最大获取硬币数。通过对这些问题的解析,展示了在编程竞赛中如何分析和解决问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A. Div. 7

题目链接

大致题意:给你一个整数n,你可以改变n的某一位,使得n没有前导0并且能够整除7,如果n本身就可以整除7,直接输出,否则输出改变后的最小的n。

题解:
如果n本身能够整除7,直接输出。
否则对于n的个位,从0~9循环列举,找到的一个能够整除n的数字即是答案。
代码

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>

#define endl '\n'

using namespace std;

int main ()
{

	ios :: sync_with_stdio(false);
	
	int T;    cin >> T;
	
	for (int j = 1; j <= T; j ++ )
	{
		int n;    cin >> n;
		
		if (n % 7 == 0)    cout << n << endl;
		else{
			n -= n % 10;
			for (int i = 0; i <= 9; i ++ )
			    if ((n + i) % 7 == 0)
				{
					cout << n + i << endl;
					break;
				}
		}
	}
	
	return 0;
}

B. Minority

题目链接

大致题意:给定一个字符串s,都是由01组成。ss是s的一个连续的字串,比较ss中的01数目,去除最少的数目的数字,如果相等则输出0。
现求能够去除的最长的数字的个数

题解:
这道题非常简单,我们首先统计s中01各自出现的次数,
如果相同则输出0或者1的个数减一,
否则输出较少的那个

代码:

#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <iomanip>

#define endl '\n'

using namespace std;

int main ()
{

    ios :: sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int T;    cin >> T;

    while (T -- )
    {
        string s;    cin >> s;
        int num[2] = {};
        for (int i = 0; i < s.length(); i ++ )    num[s[i] - 48] ++;
        if (num[0] == num[1])
            cout << num[0] - 1 << endl;
        else
            cout << min(num[0], num[1]) << endl;
    }

    return 0;
}

C. Kill the Monster

题目链接

大致题意: 人血量hc,攻击力dc。怪兽血量hm,攻击力dm。
人先攻击怪兽,然后怪兽攻击人类,直至一方血量<=0。现在,人手里有k个硬币,每个硬币可以加攻击力w,血量a。
问:人最后是否能够在硬币的帮助下打败怪兽

题解: 首先假设人的血量和攻击力已经定下来,那么是否能够打败怪兽如何计算?
非常简单,分别计算人和怪兽能够承受的最大攻击次数,然后比较。由于人是先于怪兽攻击的,所以只要人的承受次数>=怪兽的承受次数就好了。
枚举每种硬币的使用情况然后判断;

代码:

#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <iomanip>

#define endl '\n'

using namespace std;

int main ()
{

    ios :: sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int T;    cin >> T;

    while (T -- )
    {
        string s;    cin >> s;
        int num[2] = {};
        for (int i = 0; i < s.length(); i ++ )    num[s[i] - 48] ++;
        if (num[0] == num[1])
            cout << num[0] - 1 << endl;
        else
            cout << min(num[0], num[1]) << endl;
    }

    return 0;
}

D. Make Them Equal

题目链接

大致题意: 给定一个长度为n 的数组a,初始值都是1。你可以对a数组的任意一项进行操作:a[i] = a[i] + a[i] / x;x是整数。
然后给定你长度同样为n 的数组b、c,如果a[i] == b[i],那么你将获得c[i]数目的硬币
问:在进行一些操作后,能够达到的硬币的最大数目是多少

题解: 首先得认清这个问题的本质:实际上就是一个非常简单的01背包问题,c[i]就是价值,将b[i]转化以后就是重量。就是在总次数不超过k的情况下,从n个元素中能够达到的最大价值。
我们用d[i]表示将1变到i所需要的次数;

代码:

#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <iomanip>

#define endl '\n'
#define ll long long

using namespace std;

int main ()
{

    ios :: sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    const int N = 1e3 + 10;
    vector <int> d(N, N);
    d[1] = 0;
    for (int i = 1; i < N; i ++ )//枚举a[i]
        for (int x = 1; x <= i; x ++ )//枚举x
        {
            int j = i + i / x;
            if (j < N)    d[j] = min(d[j], d[i] + 1);
        }//计算次数
    
    int T;    cin >> T;

    while (T -- )
    {
        int n, k;    cin >> n >> k;

        vector <int> b(n + 10);
        vector <int> c(n + 10);
        int sum = 0;
        for (int i = 1; i <= n; i ++ )    {cin >> b[i];  b[i] = d[b[i]];  sum += b[i];}
        for (int i = 1; i <= n; i ++ )    cin >> c[i];
        k = min(k, sum);//如果k非常大,则取小一点的情况

        vector <int> f(k + 10, 0);
        for (int i = 1; i <= n; i ++ )
            for (int j = k; j >= b[i]; j -- )
                f[j] = max(f[j], f[j - b[i]] + c[i]);
        
        cout << f[k] << endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值