2023牛客寒假算法基础集训营4

A-清楚姐姐学信息论

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

不同进制对于信息的表示效率不同,清楚姐姐最近学习了信息论中使用不同进制表示信息的方法,她现在想要比较两种不同进制表示信息时,谁的效率更高。

在不引入信息论的情况下,我们可以举一个生活中具体的例子来教大家如何比较进制的信息表示效率。

在临近考试冲刺,或者形如``距离啥啥只有“XX”天的时候,往往会准备一些数字号码牌用于表示这个“XX”天,假设现在有一个倒数100100100天的需求。我们往往会准备0,1,2,3,4,5,6,7,8,90,1,2,3,4,5,6,7,8,90,1,2,3,4,5,6,7,8,9共101010种号码牌,每种号码牌各222个,使用这202020个号码牌进行排列组合就可以表示000到999999这100100100天。

也就是说对于101010进制,使用202020个号码牌就可以表示100100100个不同的数字。

现在我们思考一下,假设这个“XX”我们不再用101010进制表示,而是改为222进制表示。同样使用202020个号码牌,能够表示多少个数字?

我们发现对于222进制,使用202020个号码牌可以表示102410241024个数字,远大于101010进制下使用相同多的号码牌能够表示的数字数目。

当且仅当,xxx进制和yyy进制分别使用x⋅yx \cdot yx⋅y张号码牌时xxx进制能够表示的数字数目大于yyy进制,则称xxx进制的信息表示效率大于yyy进制。

输入描述:

输入仅一行,两个非负整数x,y(2≤x,y≤109)x,y(2 \leq x,y \leq 10^{9})x,y(2≤x,y≤109)表示清楚姐姐想要比较xxx进制和yyy进制,哪种进制的信息表示效率更高。

输出描述:

输出仅一行,一个整数ansansans,表示效率更高的进制,特别的,如果输入两种进制的信息表示效率相同,则输出进制数较小的那一个,即当xxx进制和yyy进制的信息表示效率相同时,输出min(x,y)min(x,y)min(x,y)。

示例1

输入

复制2 10

2 10

输出

复制2

2

说明

使用202020个号码牌时,222进制能表示102410241024个数字,而101010进制只能表示100100100个数字,故222进制的信息表示效率高于101010进制

示例2

输入

复制998244354 998244353

998244354 998244353

输出

复制998244353

998244353

示例3

输入

复制1000000000 1000000000

1000000000 1000000000

输出

复制1000000000

1000000000

说明

输入的xxx和yyy可能相同

//我刚开始观察样例,直接cout<<min(x,y),显然错误,我们注意看第一个样例说明那里,当我们输入2,10时,2进制能表示1024个数字,而10进制能表示100个,其实也就2^10=1024,10^2==100,那么我们分别求出他们能表示的数字,然后比较,谁大输出谁,相同输出小的那个进制,然后相等那里举个例,2^4==4^2,所有输出2.

不过直接输出min(x,y),也不是不可,除2,3这对数比较特殊,特判一下,其他的都是小数的大数次方大于大数的小数次方,同时建议用这个方法,虽然我用了long long,但应该是测试点问题,按题目所述的话还是会超过这个范围,当然也可以转换成其他形式比较。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int x,y;
    cin>>x>>y;
  long long a,b;
    a=pow(x,y);
    b=pow(y,x);
    if(a>b)cout<<x;
    else if(a==b)cout<<min(x,y);
    else cout<<y;
    return 0;
}

E-清楚姐姐打怪升级 

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

清楚姐姐玩游戏打怪升级,一共有NNN只怪物,第iii只怪物的生命值上限为hih_ihi​,生命恢复速度为viv_ivi​,清楚姐姐的攻击间隔为ttt,攻击力为aaa。

在每个时刻初,若怪物的生命值不满,则恢复viv_ivi​点生命值,但是不能超过生命值上限hih_ihi​。

在第1,1+t,1+2⋅t,1+3⋅t,...,1+k⋅t1,1+t,1+2\cdot t,1+3 \cdot t ,...,1+k \cdot t1,1+t,1+2⋅t,1+3⋅t,...,1+k⋅t个时刻末,清楚姐姐可以选择一只怪物造成aaa点伤害,若此时怪物的生命值小于等于000,则该怪物死亡。

清楚姐姐想要知道自己至少在第几个时刻末可以杀死所有怪物,或者清楚姐姐永远也无法杀死所有怪物则输出−1-1−1。

输入描述:

第一行输入三个整数N,t,a(1≤N≤105,1≤t≤106,0≤a≤106)N,t,a(1 \leq N \leq 10^{5},1\leq t \leq 10^{6},0 \leq a \leq 10^{6})N,t,a(1≤N≤105,1≤t≤106,0≤a≤106),分别表示怪物的数目,清楚姐姐的攻击间隔和攻击力。

接下来NNN行,每行输入两个整数hi,vi(1≤hi≤106,0≤vi≤106)h_i,v_i(1\leq h_i \leq 10^{6},0 \leq v_{i} \leq 10^{6})hi​,vi​(1≤hi​≤106,0≤vi​≤106),分别表示每只怪物的生命值上限和生命恢复速度。

输出描述:

仅一个整数,表示清楚姐姐至少在第几个时刻末可以杀死所有怪物,或者清楚姐姐永远也无法杀死所有怪物则输出−1-1−1。

示例1

输入

复制2 1 7 7 100 10 4

2 1 7
7 100
10 4

输出

复制3

3

说明

在第111个时刻末,清楚姐姐一刀解决第111只怪物。

在第222个时刻末,清楚姐姐攻击第222只怪物,怪物剩余血量为333。

在第333个时刻初,第222只怪物恢复444点生命,怪物剩余血量为777。

在第333个时刻末,清楚姐姐攻击第222只怪物,杀死所有怪物。

示例2

输入

复制2 100 7 3 100 10 4

2 100 7
3 100
10 4

输出

复制-1

-1

longlong一定要加,不能模拟,会超时,需要找规律。

我们每个时刻初进行攻击,并且加上时间,如果发现生命值小于等于0,那么继续下一个怪物,没死情况后,我们再判断他是不是杀不死(条件就是他的间隔时间和恢复值的乘积大于等于伤害,我们可以把间隔时间看作一次操作,如果每次操作的伤害都小于在这次操作中的恢复值那肯定杀不死,这里无需考虑在每个时刻初,若怪物的生命值不满,则恢复vi点生命值,但是不能超过生命值上限hi,因为这样的情况杀不死。

接着,我们这样理解,每次操作带来的伤害就是原本的伤害减去这次操作中这个时间段恢复的值的总量,也就是在这个时间间隔的里的这次操作中,产生的伤害就是a-t*v,我们只需要用现有的生命h去除以他,看看需要几次时间t,如果除不尽再加一次时间t,对于最后的输出,我的理解是因为从1时刻开始的,我们的x只是统计了这几次操作所需的时间t,然后-t,其实就是减去最开始1时刻与t间隔之间的差。

#include<bits/stdc++.h>
using namespace std;
int main(){
  long long int n,t,a,h,v,x=0,k=0;
    cin>>n>>t>>a;
    while(n--){
        cin>>h>>v;
       h-=a;x+=t;
        if(h<=0)continue;
        if(t*v>=a){k=1;break;}
        else {
            x+=(h/(a-t*v))*t;
            if(h%(a-t*v))
                x+=t;
        }
        
    }
    if(k==1)cout<<"-1";
    else
    cout<<x+1-t;
    return 0;
}

L-清楚姐姐的三角形I

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

众所周知,组成三角形的条件是三角形三条边满足任意两边之和大于第三边,任意两边之差小于第三边。

假设三角形的三条边分别为a,b,ca,b,ca,b,c长度分别为la,lb,lcl_a,l_b,l_cla​,lb​,lc​,且la,lb,lcl_a,l_b,l_cla​,lb​,lc​都是正整数

我们定义三角形的三个顶点分别为A,B,CA,B,CA,B,C,顶点AAA连接b,cb,cb,c两边;顶点BBB连接a,ca,ca,c两边;顶点CCC连接a,ba,ba,b两边。

定义三角形三个顶点的权值VA=lb+lc,VB=la+lc,VC=la+lbV_A=l_b+l_c,V_B=l_a+l_c,V_C=l_a+l_bVA​=lb​+lc​,VB​=la​+lc​,VC​=la​+lb​。

现在清楚姐姐已知VA,VB,VCV_A,V_B,V_CVA​,VB​,VC​的值,求la,lb,lcl_a,l_b,l_cla​,lb​,lc​的值。

输入描述:

第一行输入一个正整数T(1≤T≤105)T(1 \leq T \leq 10^5)T(1≤T≤105)表示测试案例的组数,对于每组测试案例:

输入三个正整数VA,VB,VC(1≤VA,VB,VC≤109)V_A,V_B,V_C(1\leq V_A,V_B,V_C \leq 10^{9})VA​,VB​,VC​(1≤VA​,VB​,VC​≤109)。

输出描述:

对于每组测试案例:

若存在至少一组正整数la,lb,lcl_a,l_b,l_cla​,lb​,lc​的值可以组成三角形,则首先输出'Yes',然后另起一行输出三个正整数表示la,lb,lcl_a,l_b,l_cla​,lb​,lc​的值,输出的顺序也要按照la,lb,lcl_a,l_b,l_cla​,lb​,lc​的顺序,输出的三个数之间用一个空格隔开,如果有多种解,你可以输出任意解。

否则对于该组测试案例只用输出一个字符串'No'。

裁判程序将忽略大小写,你可以输出任意大小写的'YES'和'NO'

示例1

输入

复制2 1 1 1 7 8 9

2
1 1 1
7 8 9

输出

复制No Yes 5 4 3

No
Yes
5 4 3

//这题是补题的,不过我没太明白,题目所说的如果有多解,输出任意解,我觉得解是唯一的。

提交成功后,自我总结关键点在于第一个判断,不仅需要保证任意两边之和大于第三边(我看有些还把任意两边之差小于第三边,加上了绝对值去判断,显然没有必要),还要保证求出的a,b,c能和x,y,z产生正确联系,因为我们是取整,而在计算中,会出现小数,题目中还把a,b,c是正整数进行了加粗。

#include<bits/stdc++.h>
using namespace std;
int main(){
   int t,x,y,z,a,b,c;
    cin>>t;
    while(t--){
        cin>>x>>y>>z;
        a=0,b=0,c=0;
        c=(x+y-z)/2;b=(x+z-y)/2;a=(y+z-x)/2;
        if((a+b)>c&&(a+c)>b&&(b+c)>a&&x==(b+c)&&y==(a+c)&&z==(a+b))
            cout<<"Yes\n"<<a<<' '<<b<<' '<<c<<endl;
        else cout<<"No\n";
    }
    return 0;
}

M-清楚姐姐的三角形II

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

清楚姐姐编写程序判断三条边可以组成三角形后,决定反其道而行之。

请你构造一个大小为NNN的数组,要求数组中每相邻的三项均不能组成三角形,即输出一个数组aaa,要求对于所有的ai,ai+1,ai+2a_{i},a_{i+1},a_{i+2}ai​,ai+1​,ai+2​不能组成三角形,并且你构造的数组中每一项的值在[1,109][1,10^9][1,109]范围内。

输入描述:

输入一个正整数N(1≤N≤105)N(1\leq N \leq 10^{5})N(1≤N≤105)表示数组的大小。

输出描述:

输出一行NNN个正整数aia_iai​表示数组的每个元素,要求aia_iai​的值在[1,109][1,10^9][1,109]范围内。

示例1

输入

复制10

10

输出

复制1 1 2 3 5 8 13 21 34 55

1 1 2 3 5 8 13 21 34 55

说明

1,1,2不能组成三角形。
1,2,3不能组成三角形。
2,3,5不能组成三角形。
3,5,8不能组成三角形。
5,8,13不能组成三角形。
8,13,21不能组成三角形。
13,21,34不能组成三角形。
21,34,55不能组成三角形。

 //这题有点小坑,题目就是让我们输出n个数字,每相邻三个数都不能构成三角形,也就是出现一边等于其他两边之和,我们以最小数1构成一个等边三角形,那就是1 1 1,如果使其不成立,令其一边为2即可,1 1 2,然后看着样例,第4个数字在1 2的前提是只能是3,也就是3=1+2,然后发现这不就是一个斐波那契数列嘛,从这里就入坑了,运行测试的时候,题目也说了可能有多个解。

 最后才注意到每个数的最大范围是10^9,但按斐波那契数列早就超过了,所以从最简单的1 1 2开始,然后1 1 2 1 1 2 1 1 2......以此继续下去输出前n个数即可,也满足每三个无法组成三角形,当然我们的初始循环也可以是1 2 1或2 1 1,输出任意一个都行。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,i,a[100005],y=0;
    cin>>n;
    for(i=1;i<=n;i++)
        if(i%3==0)a[i]=2;
    else a[i]=1;
    for(i=1;i<=n;i++){
        if(i!=1)cout<<' ';
        cout<<a[i];
    }
        
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星河欲转。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值