- 25级新生选拔赛
25级新生选拔赛题解
- @ 2025-12-6 20:21:45
A.棋盘4.0(剑染黎明)
- 开两数组,H,L记录每行,每列有无1。
- 对某位置,只要它所在的行或列有1,即输出1,否则输出0;
//c
#include <stdio.h>
int main(){
int n,m,x;
scanf("%d %d",&n,&m);
int H[n]={0};
int L[m]={0};
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&x);
if(x){
H[i]=1;
L[j]=1;
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(H[i]||L[j]){
printf("%d ",1);
}
else printf("%d ",0);
}
printf("\n");
}
}
B.大鱼吃小鱼(小b)
思路:每次一条鱼就增大一个单位,每增大一单位可能就能吃到刚才吃不到的鱼,由此我们想到了二次循环,但是对于已经吃过的鱼,我们可以把它的体型改成曾么都吃不到的 “巨鱼霸” 。(题目数据范围很小,不会超时)(先排序也ok,这里不做过多赘述)。
#include<stdio.h>
int main()
{
int n,l;
scanf("%d%d",&n,&l);
int a[1100];
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int ans=l;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[j]<=ans)
{
ans++;a[j]=1e9;//"巨鱼霸"
}
}
}
printf("%d",ans);
return 0;
}
C.Accepted(小b)
签到题,直接输出即可
#include<stdio.h>
int main()
{
printf("Accepted");
return 0;
}
D.dot队的荣光(涵涵)
思路:通过题面首先了解到,做题只围绕笃笃骨的激情展开,且其激情只受自身出多少技能影响,其他角色均不影响其激情,故在建立数组来存储激情变化时,每次操作我们只需要看是否为对笃笃骨即可,这样就简化了很多操作。在对笃笃骨的操作中,我们不需要在一个回合中每次操作后或在激情扣除前判断其激情是否溢出(要注意,笃笃骨在祭祀状态期间每次释放技能激情上限都会加5,永远不可能达到激情上限),最后在该回合结尾用笃笃骨的激情,与2*2(回合数)进行比较,并进行减法操作即可。若笃笃骨在该回合的激情小,将答案调整为该回合。最后输出即可。需要注意的是,该状态可能持续满四个回合,要注意该情况的判断
//笃笃骨=1 蓝手帕=2 洁西卡=3 苏芙比=4
//ddg开启大招后激情上限+5,使用咒语获得激情额外+1
//每个角色使用一次技能激情+1,基础上限为5
//ddg大招期间回合结束扣除2+2*(持续回合数)的激情,若不足则仪式结束
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int t;
cin >> t;
while(t--){
vector<int> a(5,0);
bool flag=1;
int ans=0;
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
int x;
cin >> x;
if(x==1){
if(flag) a[1]+=2;
else a[1]++;
}
}
if(flag){
int m=2+2*i;
if(a[1]>=m) a[1]-=m;
else{
a[1]=0;
flag=0;
ans=i;
}
}
}
if(flag) cout << 4 << endl;
else cout << ans << endl;
}
return 0;
}
E.赶作业(小b)
想要让总用时最少,写作业时间我们不能管,唯一可以控制的只有写最后一门作业的休息时间,所以想让总时间最少,就把休息时间最多的砍掉,就是把用时最长的一门放在最后。
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int ti = n * 60;
int a[5];
int mmax = -1;
int num = 0;
for (int i = 0; i <= 4; i++)
{
scanf("%d",&a[i]);
if(a[i]>mmax)mmax=a[i];
num += a[i];
}
num -= mmax;
num = num * 1.2;//其余用时是a[i]X(1+休息用的1/5);
num += mmax;
if (num > ti)
printf("NO");
else
printf("YES");
return 0;
}
F.梁山伯与祝英台(剑染黎明)
- 二进制是从右向左读的,右边是低位,左边是高位,逢二进一。
- 最低位的对应十进制为;
- 第二位的对应十进制为;
- 第三位的对应十进制为;
- 第四位的对应十进制为;
- ···
- 逢二进一位,每高一位对应的值翻倍;
- 如转为十进制为;
- 字符串计数需要从左向右读取。
- 用记录要读取子串的长度,记录当前字符在子串中的位置对应的十进制值;初始时等于对应子串中的最高位,每向前读一位(除以2向下取整)降低一位,当等于0时对应长为的子串就取完了。
//c
#include <stdio.h>
int main(){
int n;
scanf("%d",&n);
char s[n];
int a[50000];//存储结果
scanf("%s",s);
int temp=1,x=1,sum=0,ans=0;
for(int i=0;i<n;i++){
if(s[i]=='1'){//若为'1'加上此位值
sum+=temp;
}
temp/=2;
if(temp==0){
a[ans]=sum;
temp=1,x++,sum=0,ans++;
if(x==11)x=1;
for(int i=0;i<x-1;i++){//从左向右读取,先读取到高位,算出最高位。
temp*=2;
}
}
}
printf("%d\n",ans);
for(int i=0;i<ans;i++){
printf("%d ",a[i]);
}printf("\n");
}
- c++;中有二进制转换函数bitset<>();
//c++;
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,lenth=1;
string s;//定义字符串s;
cin>>n>>s;
vector<int> ans;//长度可变数组;
for(int i=0;i+lenth<=n;lenth=lenth%10+1)
{
string s1=s.substr(i,lenth);//从i开始截取长度为lenth的子字符串s1;
bitset<10> a(s1);//将s1转化为长度为10的二进制;
ans.push_back(a.to_ullong());//二进制转化为十进制压入数组;
i+=lenth;
}
cout<<ans.size()<<'\n';//输出数组长度;
for(int i=0;i<ans.size();i++)//依次输出结果;
cout<<ans[i]<<' ';
return 0;
}
G.鸡牛同笼 (小b)
把它想象成一个数学问题, 2x+4y==n,现在要枚举每一种情况,就是把x或y从头开始枚举即可。
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int ans=0;
for(int x=0;x<51;x++)// x是鸡,鸡最多有50个(看数据范围)
{
for(int y=0;y<26;y++)
{
if(x*2+y*4==n)ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
H.补番计划(小b)
思路:本题涉及一个简单的算法思想——滑动窗口(可以去B站上面了解一下),我们可以发现答案一定是数组里一段连续的部分,答案就是他的长度。因此我们可以根据题目去维护符合条件的连续子数组,再记录最长的长度即可。当然前缀和也能写,但俺就想写滑动窗口。
#include<stdio.h>
int main()
{
int n,t;
scanf("%d%d",&n,&t);
int a[100010];
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int l=1,r=1;// l 就是窗口左端点,r是右端点。
int ans=0,num=0;// num 记录已用时间
while(r<=n)
{
num+=a[r];
while(num>t)//当右端加入一个时长,发现超过t了,要把左端的去掉,直到再次满足
{
num-=a[l];
l++;
}
if(ans<r-l+1)ans=r-l+1;
r++;//右端点继续延伸
}
printf("%d",ans);
return 0;
}
I.无字符串(剑染黎明)
- 的码是;
- 所有大写字母的码都小于;
- 不知道没关系,输出下字符就可以得到它的码;
- 最后记得检查,余下的若为奇数会有一个大写被转为小写。
//c
#include <stdio.h>
int main(){
int n,k,x,ans=0;
scanf("%d %d",&n,&k);
char s[n];
scanf("%s",s);
for(int i=0;i<n;i++){
if(s[i]<97)ans++;
else if(k>0){
ans++;k--;
}
}
if(k%2==1)ans--;
printf("%d\n",ans);
}
J.宝光阁(剑染黎明)
- 假设在左右都取宝物,那我先取左再取右,再取左;显然不如先把左边要取得取完,再取右边,这样回头路就只有左边那一段;
- 回头路只有左段或右段;
- 相同范围,回头路走左右中较短的一段;
- 用前缀和分别来统计左右有多少宝物;
- 暴力枚举,总体运算次数不超过;
//c
#include <stdio.h>
int max(int a,int b){
return a>b?a:b;
}
int L[1000010]={0};
int R[1000010]={0};
int main(){
int n,m,x,ans=0,sum,a0=0;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++){//输入宝物位置;
scanf("%d",&x);
if(x<0)L[-x]++;
else if(x>0)R[x]++;
else a0++;//统计坐标0处宝物;
}
for(int i=1;i<1000010;i++){//前缀和;
L[i]+=L[i-1];
R[i]+=R[i-1];
}
for(int i=0;i<=m&&i<1000010;i++){//注意不要超过m和数组大小;
sum=L[i];
sum+=R[max(m-2*i,(m-i)/2)];//相同范围,回头路走左右中较短的一段;
ans=max(ans,sum);
}
ans+=a0;//结果加上坐标0处宝物数量;
printf("%d",ans);
return 0;
}
0 条评论
目前还没有评论...