17校招真题题集(1)1-5

注:本系列题目全是按照通过率降序来排列的,基本保证题目难度递增。

1、

题目名称:游戏任务标记

来源:腾讯

题目描述

游戏里面有很多各式各样的任务,其中有一种任务玩家只能做一次,这类任务一共有1024个,任务ID范围[1,1024]。请用32个unsigned int类型来记录着1024个任务是否已经完成。初始状态都是未完成。 输入两个参数,都是任务ID,需要设置第一个ID的任务为已经完成;并检查第二个ID的任务是否已经完成。 输出一个参数,如果第二个ID的任务已经完成输出1,如果未完成输出0。如果第一或第二个ID不在[1,1024]范围,则输出-1。

输入描述:

输入包括一行,两个整数表示人物ID.

输出描述:

输出是否完成

示例1

输入

1024 1024

输出

1

分析:经过(艰难的)读题,分析出只有两个数相等,才输出1,否则第二个ID一定未完成,输出0,不在范围输出-1即可。

p=(input().split())
f,s=int(p[0]),int(p[1])
if f not in range(1,1025) or s not in range(1,1025):
    print(-1)
elif s==f:
    print(1)
else:
    print(0)

当然,这可能不是题目的本意,真的这么写可能会被打。

1024=32*32,因此可用32个整数表示1024位(因为每个整数32位)
因为任务ID范围是1~1024,所以减1转化为0~1023
然后任务ID除以32,商为存到哪个整数,余数为该整数对应位(置1即可)
注:除以32相当于直接右移5位,对32取余相当于"与31"(这个技巧只对2的次方数有效).

#include <iostream>
using namespace std;
    
unsigned int arr[32];
    
int main()
{
    int id1, id2;
    while(cin>>id1>>id2)
    {
        if(!(id2>=1 && id2<=1024))
        {
            cout<<-1<<endl;
            continue;
        }
        arr[(id1-1)>>5] |= (1<<(id1&31));
        cout<<( (arr[(id2-1)>>5] & (1<<(id2&31))) != 0)<<endl;
    }
    return 0;
}

2、

题目名称:网络走法数目

来源:美团

题目描述

有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数int x,int y,请返回小团的走法数目。

输入描述:

输入包括一行,逗号隔开的两个正整数x和y,取值范围[1,10]。

输出描述:

输出包括一行,为走法的数目。

示例1

输入

3 2

输出

10

分析:

函数f(a,b)代表走到坐标(a,b)的走法数目

#include<iostream>
using namespace std;
int step(int m,int n){
    if(m == 0 || n == 0)
        return 1;
    return step(m - 1,n) + step(m,n -1);
}
int main(){
    int x,y;
    cin >> x >> y;
    cout << step(x,y) <<endl;
}

最笨写法,太多的重复子问题计算

简单动态规划

用二维表记录下来结果,并加以利用。

压缩:我们发现,除了这个位置上本身的数,DP[i,j]只和DP表中左边和上边的值有关,所以可以生成长度为矩阵较小边长一维表,用两层循环。注意顺序,从左向右打表,只有这样,左边的那个元素才是被更新过的,才是本行的左边那个元素。

l=(input().split())
x,y=int(l[0])+1,int(l[1])+1
l=[0]*x
l[0]=1
for p in range(y):
    for i in range(1,x):
        l[i]+=l[i-1]
print(l[-1])

3、

题目名称:幸运数

来源:京东

题目描述

小明同学学习了不同的进制之后,拿起了一些数字做起了游戏。小明同学知道,在日常生活中我们最常用的是十进制数,而在计算机中,二进制数也很常用。现在对于一个数字x,小明同学定义出了两个函数f(x)和g(x)。 f(x)表示把x这个数用十进制写出后各个数位上的数字之和。如f(123)=1+2+3=6。 g(x)表示把x这个数用二进制写出后各个数位上的数字之和。如123的二进制表示为1111011,那么,g(123)=1+1+1+1+0+1+1=6。 小明同学发现对于一些正整数x满足f(x)=g(x),他把这种数称为幸运数,现在他想知道,大于0且小于等于n的幸运数有多少个?

输入描述:

每组数据输入一个数n(n<=100000)

输出描述:

每组数据输出一行,小于等于n的幸运数个数。

示例1

输入

21

输出

3

分析:思想确实不难,按照题目意思走就可以了。实现稍微考察了coding能力吧,就要多练。

给出各种语言的实现:

python:

def f1(n):
    ret,t=0,n
    while 1:
        ret+= t%2
        t=t//2
        if t==0:
            break
    return ret
def f2(n):
    q=0
    for i in str(n):
        q+=int(i)
    return q
r=int(input())
k=0
for i in range(1,r+1):
    if f1(i)==f2(i):
        k+=1
print(k)

java:

package 幸运数;
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            int count = 0;
            for (int i = 1; i <= n; i++) {
                if (f(i) == g(i)) {
                    count++;
                }
            }
            System.out.println(count);
        }
    }
    /** 二进制 */
    private static int g(int n) {
        int sum = 0;
        while (n != 0) {
            sum += n % 2;
            n /= 2;
        }
        return sum;
    }
    /** 十进制 */
    private static int f(int n) {
        int sum = 0;
        while (n != 0) {
            sum += n % 10;
            n /= 10;
        }
        return sum;
    }
}

c++:

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<stdlib.h>
#define N 30;
using namespace std;
int f(int i)
{
    int sum = 0;
    while(i)
    {
        sum+=i%10;
        i/=10;
    }
    return sum;
}
int g(int i)
{
    int sum = 0;
    for(int j = 1;j<100000;j*=2)
    {
        if((j&i)==j) sum++;
    }
    return sum;
}
int main()
{
    //cout<<f(123)<<endl;cout<<g(123)<<endl;
    int n;
    while(cin>>n)
    {
        int sum = 0;
        for(int i = 1;i<=n;i++)
        {
            if(f(i)==g(i)) {sum++;}
        }
        cout<<sum<<endl;
    }
    return 0;
}

4、

题目名称:解救小易

来源:网易

题目描述

有一片1000*1000的草地,小易初始站在(1,1)(最左上角的位置)。小易在每一秒会横向或者纵向移动到相邻的草地上吃草(小易不会走出边界)。大反派超超想去捕捉可爱的小易,他手里有n个陷阱。第i个陷阱被安置在横坐标为xi ,纵坐标为yi 的位置上,小易一旦走入一个陷阱,将会被超超捕捉。你为了去解救小易,需要知道小易最少多少秒可能会走入一个陷阱,从而提前解救小易。

输入描述:

第一行为一个整数n(n ≤ 1000),表示超超一共拥有n个陷阱。
第二行有n个整数xi,表示第i个陷阱的横坐标
第三行有n个整数yi,表示第i个陷阱的纵坐标
保证坐标都在草地范围内。

输出描述:

输出一个整数,表示小易最少可能多少秒就落入超超的陷阱

示例1

输入

3
4 6 8
1 2 1

输出

3

分析:从[1,1]走到[X,Y]需要(X-1)+(Y-1)步这样对每个陷阱计算一下从[1,1]到陷阱所用的步数,求最小值即可。

n=int(input())
//保存横纵坐标
x=[int(x) for x in input().split()]
y=[int(x) for x in input().split()]
s=x[0]-y[0]-2//保存值
for i in range(n):
    s=min(x[i]+y[i]-2,s)
print(s)

5、

题目名称:身份证分组

来源:去哪网

题目描述

18位身份证的编码规则是:
前1、2位数字表示:所在省(直辖市、自治区)的代码
第3、4位数字表示:所在地级市(自治州)的代码
第5、6位数字表示:所在区(县、自治县、县级市)的代码;
第7—14位数字表示:出生年、月、日;
第15、16位数字表示:所在地的派出所的代码;
第17位数字表示性别:奇数表示男性,偶数表示女性;
第18位数字是校检码,用来检验身份证的正确性。
用户在输入身份证的过程中经常会输入错误,为了方便用户正确输入需要在输入过程中对用户的输入按照 6+8+4 的格式进行分组,实现一个方法接收输入过程中的身份证号,返回分组后的字符

输入描述:

输入数据有多行,每一行是一个输入过程中的身份证号

输出描述:

分组后的字符串

示例1

输入

5021
502104 198803
5021041988033084
502104198803308324

输出

5021
502104 198803
502104 19880330 84
502104 19880330 8324

分析:就是判断一下字符串长度的情况

s=input().replace(' ','')
if len(s)<=6:
    print(s)
elif len(s)<=14:
    print(s[0:6]+' '+s[6:])
else:
    print(s[0:6]+' '+s[6:14]+' '+s[14:])

有些同学没学python,找了个别人的c++,自己看吧

#include <iostream>
#include <string>
using namespace std;
 
//按顺序输出字符串,跳过空格
//重新确定空格的位置,输出时对非空格字符计数,6及18时输出一个空格
//注意一种特殊清空,字符串就6个,那么计数为6时不加空格
int main(){
    string s;
    while(getline(cin,s)){
        int cnt=0;
        for(int i=0;i<s.size();++i){
            if(s[i]!=' '){
                ++cnt;
                cout<<s[i];
                if(i==s.size()-1) break;
                if(cnt==6||cnt==14) cout<<" ";
            }
        }
        cout<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/hebtu666/article/details/82877294