关于Codeforces Round #592 (Div. 2)A、B、C题的题解

关于Codeforces Round #592 (Div. 2)A、B、C题的题解

说明

作为一名真·编程新手,并且这是我第一次写博客,如果有错误或者写的不好的地方,希望大家能批评指正。

A Pens and Pencils

题意很简单,给t组数据,每组5个,分别为abcdk,让你求xy,x和y均为整数。
其中,要求
xc>=a
y
d>=b
x+y<=k
做题时,我们只需要保证x和y分别能够大于等于a/c或者b/d就可以了。
编程时,注意如何让浮点数取整即可。

代码
#include<stdio.h>
int main()
{
	int t,k,pen,cil;
	double x,y;
	int a,b,c,d;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
		x=1.0*a/c;
		y=1.0*b/d;
		if(int(x)!=x)
		pen=int(x)+1;
		else
		pen=int(x);
		if(int(y)!=y)
		cil=int(y)+1;
		else
		cil=int(y);
		if(pen+cil>k)
		printf("-1\n");
		else
		printf("%d %d\n",pen,cil);
	}
	return 0;
}

B Rooms and Staircases

题意

N这个人有两层楼,两层楼各层房间数是一样的。有的房间有梯子,支持上下连通,标记为1;有的房间没有梯子,标记为0。

问:N可以从任意一个房间出发,在不重复经过房间时,经过房间数最大为多少?

分析

我们可以推断,假设一个梯子也没有,那么N途径最大房间数,就是一层的房间数。
如果在第x个房间有一个梯子,无论这个梯子在哪里,N都可以从距离这个梯子最远的一头出发,沿着梯子下楼(或者上楼),再按相反的方向走到头。那么此时途径的最大房间数,就是一层经过房间数的二倍。
就算有多个梯子,我们也可以无视前几个经过的梯子,只需要从距离我们最远的那个梯子下楼(或者上楼)就可以了。

也就是说,在输入的时候,我们只需要标记最远梯子的位置即可。由于可以从左边或者右边出发,所以我标记两个梯子,分别是从左数最远的梯子,从右边数最远的梯子。
为了防止重复记录,我以中间的房间作为边界,左边最远的梯子不超过中间,右边也是
我做的时候,用了两个变量,分别是num1和num2,num1表示从左边数距离最远,num2表示从右边数距离最远。
在输入时候就对梯子进行标记。
最后只需要判断从左走还是从右走距离最远即可。另外,还要用一个变量flag来标记是否有梯子。对于输入,我用字符数组来存取,注意在输入数字后,要用getchar吃掉回车,再输入01字符串。

#include<stdio.h>
int main()
{
	int t,n,num1,num2,i,j,flag;
	char room[1010];
	scanf("%d",&t);
	while(t--)
	{
		num1=2000;num2=0,flag=0;
		scanf("%d",&n);
		getchar();
		for(i=1;i<=n;i++)
		{
			scanf("%c",&room[i]);
			if(room[i]=='1')
			{
				if(i<=n/2&&i<num1)
				num1=i;
				else if(i>n/2&&i>num2)
				num2=i;
			}
		}
		if(num1==2000&&num2==0)
		printf("%d\n",n);
		else
		{
			if(n-num1+1>=num2)
			printf("%d\n",(n-num1+1)*2);
			else
			printf("%d\n",(num2)*2);
		}
	}
	return 0;
}

C The Football Season

题意

给n,p,w,d四个整数,分别代表了n场比赛,总得分为p,赢一场得分为w,平局一场得分为d,其中,输一场不得分。
输出x,y,z,分别是胜局次数,平局次数,败局次数。其中x,y,z的答案不唯一。

分析

原本以为这是一道wx+dy=p的解方程问题,可以用扩展欧几里得来解。但是后来发现数据规模较大,已经达到了1e17,所以用扩展欧几里得是不可以的。但是w和d的范围较小,只有1e5,所以可以暴力枚举求解。

在暴力枚举求解的时候,我在test 6中出现了超时。于是我开始改进算法。
首先,我改为从x=p/w,做x- -来计算,因为w严格大于d,所以x的取值范围较小,这样可以减少运算次数。但是仍旧超时。
于是,我又调用了GCD,求公因数的函数。利用这个函数,来求w和d的最大公因数。因此可以从第一次出现(p-xw)%d==0,即wx+d*y=p的时候,每一次都让x减去他们的最大公因数,这样也可以减少运算次数,但是依旧超时。无奈之下,只好百度,发现AC代码都很简单,这也许就是大简至真吧。

AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, p, w, d;
int main()
{
    cin >> n >> p >> w >> d;
    for(ll y = 0, x; y < w; y++){
        if((p-d*y)%w==0) x = (p-d*y)/w;
        if(x >= 0 && x + y <= n){
            cout << x << " " << y << " " << n-x-y << endl;
            return 0;
        }
    }
    puts("-1");
    return 0;
}

我的代码肯定有问题,希望大神能看一眼,批评指正

菜鸡的超时代码
#include<bits/stdc++.h>
long long GCD(long long a,long long b)
{
    if(a == 0)
        return b;
    else if(b == 0)
        return a;
    else if(a == b)
        return a;
    long long mod = a % b;
    while(mod != 0)
    {
        a = b;
        b = mod;
        mod = a % b;
    }
    return b;
}
int main()
{
	__int64 n,p,w,d;
	__int64 win=0,draw=0,los=0;
	scanf("%lld%lld%lld%lld",&n,&p,&w,&d);
	__int64 i,temp;
	i=GCD(w,d);
	for(win=p/w;win>=0;)
	{
		temp=win*w;
		if((p-temp)%d==0)
		{
			los=(p-temp)/d;
			if(win+los<=n)
			{
				printf("%lld %lld %lld\n",win,los,n-win-los);
				break;
			}
			win-=i;
		}
		else
		win--;
	}
	if(win<0)
	printf("-1\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值