题目:[信息与未来 2019] 鸡兔同笼
题号:B3754
难度:普及一
题目分析
在原始的鸡兔同笼基础上,加入了三脚猫变量,让整体的灵活性提升,
但实际上基础逻辑并没有太大转变,整体分析起来还是挺舒服的。
题目要求在给出头和脚的数量情况下,求出兔子的最大最小数量。
思路
给出参数 head 和 leg
假设全是鸡,得到腿脚数量 leg_chick = 2*head.
假设全是三脚猫,得到腿脚数量 leg_cat = 3*head.
假设全是兔子,得到腿脚数量 leg_rabbit = 4*head.
如果 leg = leg_chick 很显然 全是鸡,则chick_n = head cat_n = 0 rabbit_n = 0
如果 leg_chick < leg <= let_cat ,其中多的腿数,是多腿动物与鸡的差值决定。
每多一条腿,都可以是三脚猫的,每多两条腿就可能是兔子的。
此时也可以没有兔子,因为在leg <= let_cat 的情况下,多余的腿可以只用三脚猫来补齐。
所以此时rabbit_min = 0;
而兔子的最大数量,取决于多与leg_chick的腿数,每多两条就可以有一个兔子,如果是奇数的话,例如多三条,则是一只兔子和一只三脚猫一起来补齐,所以用多的腿数除于二,向下取整,就是兔子的最大数量,由于C语言整数的自动向下取整,所以只需rabbi_max = (leg - leg_chick)/2;
最后一种情况就是
leg_cat < leg <= leg_rabbit ,此时由于腿的数量大于全是猫的数量,所以一定存在兔子,
且兔子的最少数量 rabbit_min = leg - leg_cat ,因为三脚猫与兔子差一只脚。
此时的rabbi_max = (leg - leg_chick)/2;与上一种情况保持一致。
数量关系
再说的直接一些可以是,有以下关系。
//本来有t个头,x只脚 (x>=2*t)
//x==2*t时,全是鸡
//x>2*t时,一定存在除了鸡之外的动物
//对于 x - 2*t 只脚,则多在三脚猫和兔子身上
//如果,2*t<x<=3*t,则可以没有兔子,(兔子min=0)只使用三脚猫也能补齐剩下的腿。
//如果,2*t<x<=3*t,也可以有兔子,(兔子max=(x-2*t)/2向下取整)(然后三只猫补齐剩下的腿)
//如果,3*t<x<=4*t,只有三脚猫就不够了,
// 一定存在兔子补齐剩下的腿。且(兔子min=x-3*t)(兔子max=(x-2*t)/2向下取整)
代码函数
用两个函数,利用上述思路分析的关系分别输出兔子的最小值和最大值
(其中后两种情况的最大值关系计算相同,所以合并为一种)
long long rabbit_max(long long h,long long x){
long long max;
if(x<=2*h) return 0;
return (x-2*h)/2;
}
long long rabbit_min(long long h,long long x){
if(x<=3*h) return 0;
else return x-3*h;
}
由于本题是计算不同组的结果,所以我这里采用的是结构体的一维数组,
结构体中存储头和腿的数量
struct stu{
long long head;
long long leg;
}a[22];
总代码
//本来有t个头,x只脚 (x>=2*t)
//x==2*t时,全是鸡
//x>2*t时,一定存在除了鸡之外的动物
//对于 x - 2*t 只脚,则多在三脚猫和兔子身上
//如果x是奇数,则一定有三脚猫的存在。
//如果,2*t<x<=3*t,则可以没有兔子,(兔子min=0)只使用三脚猫也能补齐剩下的腿。
//如果,2*t<x<=3*t,也可以有兔子,(兔子max=(x-2*t)/2向下取整)(然后三只猫补齐剩下的腿)
//如果,3*t<x<=4*t,只有三脚猫就不够了,
// 一定存在兔子补齐剩下的腿。且(兔子min=x-3*t)(兔子max=(x-2*t)/2向下取整)
#include <stdio.h>
struct stu{
long long head;
long long leg;
}a[22];
long long rabbit_max(long long h,long long x){
long long max;
if(x<=2*h) return 0;
return (x-2*h)/2;
}
long long rabbit_min(long long h,long long x){
if(x<=3*h) return 0;
else return x-3*h;
}
int main() {
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
scanf("%lld %lld",&a[i].head,&a[i].leg);
for(int i=1;i<=T;i++){
long long max=rabbit_max(a[i].head,a[i].leg);
long long min=rabbit_min(a[i].head,a[i].leg);
printf("%lld %lld\n",min,max);
}
return 0;
}
总结
本题通过引入三脚猫这一新的变量来赋予本题更大的灵活性,但是基础逻辑并未有实质性改变,总体来说,分析的时候很清晰,思路抒清,会很舒服。难度偏易。某种意义上来说,本题更偏向是一道数学题。
为什么这样说,因为甚至使用线性规划都能写。