1. 程式人生 > >17校招真題題集(1)1-5

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;
    }
}