关于Codeforces Round #592 (Div. 2)A、B、C题的题解
说明
作为一名真·编程新手,并且这是我第一次写博客,如果有错误或者写的不好的地方,希望大家能批评指正。
A Pens and Pencils
题意很简单,给t组数据,每组5个,分别为a、b、c、d、k,让你求x和y,x和y均为整数。
其中,要求
xc>=a
yd>=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;
}