Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1)前三题题解

传送门

A

题意

用火柴棍表示加法等式,等式要符合数学运算,1用一根火柴,8用8根。给你n根火柴根,问能构成等式所需火柴根还差多少。n可以不够,但是一定要用完。问还需要的火柴根的最小值。

输入

输入q组询问,每组输入n根火柴

输出

输出还需要火柴根数的最小值

分析

我们可以列一个等式a+b=(a+b),所需要的火柴根数为a+b+(a+b),即2(a+b),一定是一个偶数。
也就是说,对于n来说,若n是偶数(且n大于2,n为2的时候答案就是2),不需要额外的火柴就可以构成一个等式;若n是奇数(题中输入时候n大于1),只需要再加一根就可以构成偶数根火柴。
答案就很明确了。

代码
#include<stdio.h>
int main()
{
	int q,n;
	scanf("%d",&q);
	while(q--)
	{
		scanf("%d",&n);
		if(n<=3)
		printf("%d\n",4-n);
		else
		printf("%d\n",n%2);
	}
	return 0;
}

B

题意

给两个字符串,分别是s和t,对于相邻的两个字符,可以进行赋值操作,如把a1的值赋给a2,或者把a2的值赋给a3。题中有很关键的一点是,对两个字符串都可以进行操作,问两个字符串经过若干次操作后是否能变成相同的字符串。

输入

输入q,表示q次询问,每次询问输入两个字符串,分别是s和t。

输出

对于每次输出,输出“YES”或者“NO”。题中说明,输出格式不限,用“YES”举的例子,我的理解是,对于“YES”和“NO”,大小写都无所谓。但是我都输出小写的时候,答案是错误的,但我把答案改成了都是大写就对了。

分析

这道题只需要保证两个字符串中有一个单词相同就可以了。因为对于每一个字符串来说,可以经过若干次操作,把整个字符串变为只有一个字符构成的字符串。所以,只要有一个相同的字符就可以了。我选择用一个数组a【26】来存储s中出现的所有字母,只要有一个相同,那么就可以退出循环结束。

代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,flag;
	string s,t;
	scanf("%d",&n);
	while(n--)
	{
		flag=0;
		int a[28]={0};
		cin>>s;
		cin>>t;
		int len=s.size();
		int i,temp;
		for(i=0;i<len;i++)
		{
			a[s[i]-'a']=1;
		}
		for(i=0;i<len;i++)
		{
			if(a[t[i]-'a']==1)
			{
				flag=1;break;
			}
		}
		if(flag==1)
		printf("YES\n");
		else
		printf("NO\n");
	}
	return 0;
}

C

题意

输入q个询问,n表示有几张票,下面输入n个票价,然后输入x和a、y和b,k。表示从排名为a的倍数的票中抽取票价的x%,表示从排名为b的倍数的票中抽取票价的y%,问抽取总数是否能大于等于k。如果不能大于,输出-1;如果能大于,输出抽取票的最小数量。
注意:此处的抽取票数,是指从第一张开始,直到最后一个提取票价的为止。

首先,我们可以看得出,因为票的顺序是可以改变的,所以我们可以调整顺序使得价值序号为a和b的公倍数的票价值最大,如果x大于y,那么让序号为a的票的价值最大,再从剩余的中挑选最大的给b。在此基础上,我们要用二分法查找答案,这样会快一些。利用前缀和查找答案可以把时间复杂度降至O(n)
注意数据范围
关于二分法的介绍,这一篇博客比较好,推荐一下。
浅谈二分答案
我自己调了一个程序,但是一直有问题,只好从网上摘了一个,他的代码没有注释,我加几点注释,以便大家阅读。
代码出处

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 2e5+10;

int Val[MAXN];
LL Sum[MAXN];
LL n, x, y, a, b, lcm;
LL k;

bool Check(int mid)
{
    int cnta = mid/a;//在卖的mid张票中,为a的倍数的票有cnta张 
    int cntb = mid/b;//在卖的mid张票中,为b的倍数的票有cntb张
    int cnts = mid/lcm;//在卖的mid张票中,为a和b的公倍数的票有cnts张
    cnta -= cnts, cntb -= cnts;//我觉得这一步可有可无 
    LL sum = 0;
    sum += (Sum[cnts]/100)*(x+y);//把最有价值的留给公倍数 
    sum += ((Sum[cnts+cnta]-Sum[cnts])/100)*x;//计算只抽取x%的 
    sum += ((Sum[cnts+cnta+cntb]-Sum[cnts+cnta])/100)*y;//计算只抽取y%的 
    if (sum >= k)//能否达到目标 
        return true;
    return false;
}

int main()
{
    ios::sync_with_stdio(false);//加快运行速度 
    cin.tie(0);//提高cin输入流运行速度 
    int t;
    cin >> t;
    while (t--)
    {
        cin >> n;
        for (int i = 1;i <= n;i++)
            cin >> Val[i];
        cin >> x >> a;
        cin >> y >> b;
        cin >> k;
        if (x < y)
            swap(x, y), swap(a, b);//保证x永远比y大 
        sort(Val+1, Val+1+n, greater<int>());//对票价进行排序,按照从高往低排序 
        Sum[0] = 0;
        for (int i = 1;i <= n;i++)
            Sum[i] = Sum[i-1]+Val[i];//计算前i个票价总和,记录在sum中 
        lcm = (a*b)/__gcd(a, b);//求a和b的最小公倍数 
        int l = 1, r = n, res = n+1;//l是左标记,r是右标记,res表示需要卖的最小票数 
        while (l <= r)//二分查找 
        {
            int mid = (l+r)/2;//先假设卖mid张票就够了 
            if (Check(mid))//如果够了的话 
            {
                res = min(res, mid);//更新需要卖的最小票数 
                r = mid-1;//看看卖mid/2张可不可以 
            }
            else
                l = mid+1;//如果不行就多卖几张 
        }
        if (res == n+1)//全卖了也不行 
            puts("-1");
        else
            printf("%d\n", res);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值