2019 年实验班选拔试题

1.最大公约数(10分)
题目描述:已知两个正整数 a a a b b b,求这两个数的最大公约数 G C D ( a , b ) GCD(a,b) GCD(a,b)
输入格式:测试数据包括多组数据。测试数据的第一行是一个整数 n   ( n < 50 ) n\ (n<50) n (n<50),表示有 n n n组输入数据。其后有 n n n行数据,每行数据包括由空格分隔的两个正整数 a a a b b b
输出格式:对于每组测试数据,输出一行,给出对应输入数据的 G C D ( a , b ) GCD(a,b) GCD(a,b)

输入样例:
1
24 16
输出样例:
8

欧几里得算法,单次计算复杂度为 O ( l o g ( a + b ) ) O(log(a+b)) O(log(a+b))
C++ 内置 __gcd() 函数。

#include<bits/stdc++.h>

using namespace std;
int T, x, y;

//int gcd(int a, int b) {
//    return b ? gcd(b, a % b) : a;
//}

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &x, &y);
        printf("%d\n", __gcd(x, y));
    }
    return 0;
}

2.连续素数的和(10分)
题目描述:一些正整数能够表示为一个或多个连续素数的和。给出一个正整数,有多少个这样的表示?例如,整数 53 53 53有两个表示,分别是: 5 + 7 + 11 + 13 + 17 5+7+11+13+17 5+7+11+13+17 53 53 53;整数 41 41 41有三个表示,分别是: 2 + 3 + 5 + 7 + 11 + 13 2+3+5+7+11+13 2+3+5+7+11+13 11 + 13 + 17 11+13+17 11+13+17 41 41 41;整数 3 3 3只有一个表示 3 3 3;整数 20 20 20没有这样的表示。注意,这里要求必须是连续的素数相加,因此对于整数 20 20 20 7 + 13 7+13 7+13 3 + 5 + 5 + 7 3+5+5+7 3+5+5+7,都不是有效的表示。请写出一个程序,对于给出的正整数,给出连续素数的和的表示数。
输入格式:测试数据包括多组数据。每一行是一个正整数 n n n 2 ≤ n ≤ 10000 2≤n≤10000 2n10000。输入数据的最后一行为 0 0 0,表示输入结束。
输出格式:对于每组测试数据(除了输入数据最后一行的 0 0 0),输出一行。输出的每一行,对应输入的正整数,给出连续素数和的表示数量。输出中没有其它的字符。

输入样例:
2
3
17
41
20
666
12
53
0
输出样例:
1
1
2
3
0
0

首先利用线性筛法筛出前 10000 10000 10000个数中的素数,然后求前缀和,存在数组 p p p中。对于每个数 x x x,寻找有几对 i i i j j j,使得 p [ i ] + x = p [ j ] p[i]+x=p[j] p[i]+x=p[j],统计的数量即为答案。

#include<bits/stdc++.h>

using namespace std;
const int N = 1e4 + 10;
int v[N], p[N], tot;
unordered_map<int, bool> e;

inline void primes(int n) {
    for (int i = 2; i <= n; i++) {
        if (v[i] == 0)v[i] = i, p[++tot] = i;
        for (int j = 1; j <= tot; j++) {
            if (p[j] > v[i] || p[j] > n / i)break;
            v[i * p[j]] = p[j];
        }
    }
    for (int i = 1; i <= tot; i++)p[i] += p[i - 1], e[p[i]] = true;
}

inline int solve(int x) {
    int cnt = 0;
    for (int i = 0; p[i] + x <= p[tot]; i++)
        if (e[p[i] + x])cnt++;
    return cnt;
}

int main() {
    primes(10000);
    int n;
    while (scanf("%d", &n), n)
        printf("%d\n", solve(n));
    return 0;
}

3.487-3279(20分)
题目描述:企业在广告推广中,喜欢使用容易记住的电话号码。让电话号码容易记的一种方法是,将电话号码写成容易记住的单词或短语。例如,如果你要给滑铁卢大学打电话时,可以拨打TUT-GLOP。有时,只将电话号码中的部分数字拼写成单词。例如,可以拨打310-GINO向Gino定一份披萨。让电话号码容易记的另一种方法是,以一种好记的方式对号码的数字分组。例如拨打必胜客的“三个十”号码3-10-10-10,也可以定披萨。
电话号码的标准格式是七位十进制数,并在第三、第四位数字之间有个一个连接符。电话拨号盘提供了从字母到数字的映射,映射关系如下:
A、B和C映射到2;
D、E和F映射到3;
G、H和I映射到4;
J、K和L映射到5;
M、N和0映射到6;
P、R和S映射到7;
T、U和V映射到8;
W、X和Y映射到9。
Q和Z没有映射到任何数字,连字符不需要拨号,可以任意添加和删除。TUT-GLOP的标准格式是888-4567,310-GINO的标准格式是310-4466,3-10-10-10的标准格式是310-1010。
如果两个号码有相同的标准格式,那么它们就是等同的(相同的拨号)。请编写一个程序,检查电话号码簿中的电话号码中是否有相同的电话号码。
输入格式:测试数据包括多组数据。测试数据的第一行是一个正整数 n   ( n ≤ 100000 ) n\ (n≤100000) n (n100000),表示电话号码簿中号码的数量。其后有n行数据,每行数据是一个电话号码,每个电话号码由数字、大写字母(除了Q和Z)以及连接符组成。每个电话号码中只会刚好有 7 7 7个数字或字母。
输出格式:对于电话号码簿中每个出现重复的号码产生一行输出,输出号码的标准格式紧限一个空格,然后是该号码重复的次数。如果存在多个重复的号码,则按照号码的字典序升序输出。如果输入数据中没有重复的号码,输出一行:No duplicates.

输入样例:
12
4873279
ITS-EASY
888-4567
3-10-10-10
888-GLOP
TUT-GLOP
967-11-11
310-GINO
F101010
888-1200
-4-8-7-3-2-7-9-
487-3279
输出样例:
310-1010 2
487-3279 4
888-4567 3

利用map统计个数即可,map内部已经把键按字典序升序排序,个数大于1的直接输出键和值即可。

#include<bits/stdc++.h>

using namespace std;
map<char, char> mp;
map<string, int> cnt;
int n;

int main() {
    mp['A'] = mp['B'] = mp['C'] = '2';
    mp['D'] = mp['E'] = mp['F'] = '3';
    mp['G'] = mp['H'] = mp['I'] = '4';
    mp['J'] = mp['K'] = mp['L'] = '5';
    mp['M'] = mp['N'] = mp['O'] = '6';
    mp['P'] = mp['R'] = mp['S'] = '7';
    mp['T'] = mp['U'] = mp['V'] = '8';
    mp['W'] = mp['X'] = mp['Y'] = '9';
    scanf("%d", &n);
    while (n--) {
        string s1, s2;
        cin >> s1;
        for (auto it:s1) {
            if (it == '-')continue;
            else if (it >= '0' && it <= '9')s2.push_back(it);
            else s2.push_back(mp[it]);
        }
        cnt[s2]++;
    }
    bool flag = false;
    for (auto it:cnt)
        if (it.second > 1) {
            flag = true;
            for (int i = 0; i <= 2; i++)putchar(it.first[i]);
            putchar('-');
            for (int i = 3; i <= 6; i++)putchar(it.first[i]);
            putchar(' ');
            printf("%d\n", it.second);
        }
    if (!flag)puts("No duplicates.");
    return 0;
}

4.Where Amazing Happens(20分)
Problem Description
As the premier men’s professional basketball league in the world, the National Basketball Association (NBA) has witnessed many superstars, legendary teams and precious friendships.
Here is a list of every season’s champion from the league’s inception in 1946 to 2019.
Season Champion
2018-19 Toronto Raptors
2017-18 Golden State Warriors
2016-17 Golden State Warriors
2015-16 Cleveland Cavaliers
2014-15 Golden State Warriors
2013-14 San Antonio Spurs
2012-13 Miami Heat
2011-12 Miami Heat
2010-11 Dallas Mavericks
2009-10 L.A. Lakers
2008-09 L.A. Lakers
2007-08 Boston Celtics
2006-07 San Antonio Spurs
2005-06 Miami Heat
2004-05 San Antonio Spurs
2003-04 Detroit Pistons
2002-03 San Antonio Spurs
2001-02 L.A. Lakers
2000-01 L.A. Lakers
1999-00 L.A. Lakers
1998-99 San Antonio Spurs
1997-98 Chicago Bulls
1996-97 Chicago Bulls
1995-96 Chicago Bulls
1994-95 Houston Rockets
1993-94 Houston Rockets
1992-93 Chicago Bulls
1991-92 Chicago Bulls
1990-91 Chicago Bulls
1989-90 Detroit Pistons
1988-89 Detroit Pistons
1987-88 L.A. Lakers
1986-87 L.A. Lakers
1985-86 Boston Celtics
1984-85 L.A. Lakers
1983-84 Boston Celtics
1982-83 Philadelphia 76ers
1981-82 L.A. Lakers
1980-81 Boston Celtics
1979-80 L.A. Lakers
1978-79 Seattle Sonics
1977-78 Washington Bullets
1976-77 Portland Trail Blazers
1975-76 Boston Celtics
1974-75 Golden State Warriors
1973-74 Boston Celtics
1972-73 New York Knicks
1971-72 L.A. Lakers
1970-71 Milwaukee Bucks
1969-70 New York Knicks
1968-69 Boston Celtics
1967-68 Boston Celtics
1966-67 Philadelphia 76ers
1965-66 Boston Celtics
1964-65 Boston Celtics
1963-64 Boston Celtics
1962-63 Boston Celtics
1961-62 Boston Celtics
1960-61 Boston Celtics
1959-60 Boston Celtics
1958-59 Boston Celtics
1957-58 St. Louis Hawks
1956-57 Boston Celtics
1955-56 Philadelphia Warriors
1954-55 Syracuse Nats
1953-54 Minneapolis Lakers
1952-53 Minneapolis Lakers
1951-52 Minneapolis Lakers
1950-51 Rochester Royals
1949-50 Minneapolis Lakers
1948-49 Minneapolis Lakers
1947-48 Baltimore Bullets
1946-47 Philadelphia Warriors

(quoted from http://www.nba.com/history/nba-season-recaps/)

Given the team name, it won’t be difficult for you to count how many times this team(with exactly the same name) has made amazing happen.
Input
The first line gives the number of test cases. Each case contains one string S representing the team to be queried. ( T < = 30 ) (T<=30) (T<=30).S consists of English letters, digits, punctuations and spaces. And 1 < = l e n g t h ( S ) < = 30 1<=length(S)<=30 1<=length(S)<=30.
Output
For each test case, output one line containing “Case #x: y”, where x is the test case number (starting from 1 1 1) and y is the times this team has won the championship according to the list above.

Sample Input
2
Cleveland Cavaliers
Oklahoma City Thunder
Sample Output
Case #1: 1
Case #2: 0

打表。

#include<bits/stdc++.h>

using namespace std;
int T;
multiset<string> s = {
        "Toronto Raptors",
        "Golden State Warriors",
        "Golden State Warriors",
        "Cleveland Cavaliers",
        "Golden State Warriors",
        "San Antonio Spurs",
        "Miami Heat",
        "Miami Heat",
        "Dallas Mavericks",
        "L.A. Lakers",
        "L.A. Lakers",
        "Boston Celtics",
        "San Antonio Spurs",
        "Miami Heat",
        "San Antonio Spurs",
        "Detroit Pistons",
        "San Antonio Spurs",
        "L.A. Lakers",
        "L.A. Lakers",
        "L.A. Lakers",
        "San Antonio Spurs",
        "Chicago Bulls",
        "Chicago Bulls",
        "Chicago Bulls",
        "Houston Rockets",
        "Houston Rockets",
        "Chicago Bulls",
        "Chicago Bulls",
        "Chicago Bulls",
        "Detroit Pistons",
        "Detroit Pistons",
        "L.A. Lakers",
        "L.A. Lakers",
        "Boston Celtics",
        "L.A. Lakers",
        "Boston Celtics",
        "Philadelphia 76ers",
        "L.A. Lakers",
        "Boston Celtics",
        "L.A. Lakers",
        "Seattle Sonics",
        "Washington Bullets",
        "Portland Trail Blazers",
        "Boston Celtics",
        "Golden State Warriors",
        "Boston Celtics",
        "New York Knicks",
        "L.A. Lakers",
        "Milwaukee Bucks",
        "New York Knicks",
        "Boston Celtics",
        "Boston Celtics",
        "Philadelphia 76ers",
        "Boston Celtics",
        "Boston Celtics",
        "Boston Celtics",
        "Boston Celtics",
        "Boston Celtics",
        "Boston Celtics",
        "Boston Celtics",
        "Boston Celtics",
        "St. Louis Hawks",
        "Boston Celtics",
        "Philadelphia Warriors",
        "Syracuse Nats",
        "Minneapolis Lakers",
        "Minneapolis Lakers",
        "Minneapolis Lakers",
        "Rochester Royals",
        "Minneapolis Lakers",
        "Minneapolis Lakers",
        "Baltimore Bullets",
        "Philadelphia Warriors"
};

int main() {
    scanf("%d", &T);
    getchar();
    for (int i = 1; i <= T; i++) {
        string a;
        getline(cin, a);
        printf("Case #%d: %d\n", i, s.count(a));
    }
    return 0;
}

5.数字排序(40分)
题目描述:已知两个整数序列 A = ( a 1 , a 2 , a 3 , . … , a n ) A=(a_1,a_2,a_3,.…,a_n) A=(a1,a2a3,.,an) B = ( b 1 , b 2 , b 3 … , b m ) B=(b_1,b_2,b_3…,b_m) B=(b1,b2,b3,bm),将 a i   ( 1 < i ≤ n ) a_i \ (1<i≤n) ai (1<in)乘以 b j   ( 1 ≤ j ≤ m ) b_j \ (1≤j≤m) bj (1jm),产生一个有着 m ∗ n m*n mn个整数的新序列。请编写一个程序,将新序列按照升序排序,并找到排序后的第 k k k个数字。
输入格式:测试数据包括多组数据。
每组测试数据的第一行是三个整数 n   ( 1 ≤ n ≤ 10000 ) n\ (1≤n≤10000) n (1n10000) m   ( 1 ≤ m ≤ 10000 ) m\ (1≤m≤10000) m (1m10000) k   ( 1 ≤ k ≤ m ∗ n ) k\ (1≤k≤m*n) k (1kmn)
第二行包含有 n n n个整数,表示序列 A A A
第三行包含有 m m m个整数,表示序列 B B B
序列 A A A B B B中的所有整数都位于区间 [ 0 , 10000 ] [0,10000] [010000]
每组测试数据之后有一个空行。
输出格式:对于每组测试数据,输出一行,给出对应测试数据的结果。

输入样例:
1 3 3
1
3 2 1

3 3 7
1 2 3
1 2 3
输出样例:
3
6

先将数组 a a a b b b按从小到大排序,然后二分第 k k k个数的值,check函数操作类似于双指针,从大到小枚举 a a a,当枚举到 i i i时找到最大的 j j j使得 b [ j + 1 ] ⋅ a [ i ] < = x b[j + 1] ·a[i] <= x b[j+1]a[i]<=x则枚举到 i − 1 i-1 i1时找到的 j ′ j' j一定满足 j ′ ≥ j j'≥j jj,因此继续从原来的 j j j枚举。
总体复杂度为 O ( n log ⁡ n 2 ) O(n\log n^2) O(nlogn2)

#include<bits/stdc++.h>

using namespace std;
const int N = 1e4 + 10;
int a[N], b[N], n, m, k;

inline bool check(int x) {
    int cnt = 0, j = 0;
    for (int i = n; i >= 1; i--) {
        while (j < m && b[j + 1] * a[i] <= x)j++;
        cnt += j;
    }
    return cnt >= k;
}

int main() {
    while (scanf("%d%d%d", &n, &m, &k) != EOF) {
        for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
        for (int i = 1; i <= m; i++)scanf("%d", &b[i]);
        sort(a + 1, a + 1 + n);
        sort(b + 1, b + 1 + m);
        int l = 0, r = a[n] * b[m], ans;
        while (l <= r) {
            int mid = (l + r + 1) >> 1;
            if (check(mid))r = mid - 1, ans = mid;
            else l = mid + 1;
        }
        printf("%d\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_sky123_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值