1. 求和号(10 分)
    题目描述:在数学运算中经常要计算连续的和。例如,计算 1 + 2 + ⋯ + n 1 + 2 + ⋯ + n 1+2+⋯+n,或者等比数列 a + a 2 + ⋯ + a n a + a^2 + ⋯ + a^n a+a2+⋯+an。我们使用求和号在“ ∑ ∑ ∑”来表示这类连续的和。
    通常在“ ∑ ∑ ∑”的下方标自变量名称和初始值,在“ ∑ ∑ ∑”的上方标终止值,在“ ∑ ∑ ∑”的右方写表达式,求和号也可以嵌套使用,例如:
    ∑ i = 1 3 ∑ j = 1 2 a i b j = a 1 b 1 + a 1 b 2 + a 2 b 1 + a 2 b 2 + a 3 b 1 + a 3 b 2 \sum\limits_{i=1}^{3}\sum\limits_{j=1}^{2}a_ib_j=a_1b_1+a_1b_2+a_2b_1+a_2b_2+a_3b_1+a_3b_2 i=1∑3​j=1∑2​ai​bj​=a1​b1​+a1​b2​+a2​b1​+a2​b2​+a3​b1​+a3​b2​
    试编写程序计算 ∑ i = 1 n ∑ j = 1 m a i b j \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}a_ib_j i=1∑n​j=1∑m​ai​bj​。
    输入格式:第 1 行有两个整数, n n n 和 m m m。以下第 2 2 2 行到第 n + 1 n+1 n+1 行,每行包含一个整数,第 i + 1 i+1 i+1 行表示 a i a_i ai​的值。紧接着从第 n + 2 n+2 n+2 行到第 n + m + 1 n+m+1 n+m+1 行,每行包含一个整数,第 i + n + 1 i+n+1 i+n+1 行表示 b j b_j bj​的值。每次输入只包含一组测试数据。数据范
    围: 1 ≤ n , m ≤ 100000 1 ≤ n,m ≤ 100000 1≤n,m≤100000,所有整数的绝对值 ≤ 10000 ≤10000 ≤10000。
    输出格式:对每组测试数据输出一行,仅含一个整数,即你计算得到的答案。
输入样例:
3 2
1
2
3
5
7
输出样例:
72

由于 1 ≤ n , m ≤ 100000 1 ≤ n,m ≤ 100000 1≤n,m≤100000,直接计算会超时,因此将公式转换为 ∑ i = 1 n ∑ j = 1 m a i b j = b 1 ⋅ ∑ i = 1 n a i + b 2 ⋅ ∑ i = 1 n a i + . . . + b m ⋅ ∑ i = 1 n a i = ∑ i = 1 n a i ⋅ ∑ i = 1 m b i \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}a_ib_j=b_1·\sum\limits_{i=1}^{n}a_i+b_2·\sum\limits_{i=1}^{n}a_i+...+b_m·\sum\limits_{i=1}^{n}a_i=\sum\limits_{i=1}^{n}a_i·\sum\limits_{i=1}^{m}b_i i=1∑n​j=1∑m​ai​bj​=b1​⋅i=1∑n​ai​+b2​⋅i=1∑n​ai​+...+bm​⋅i=1∑n​ai​=i=1∑n​ai​⋅i=1∑m​bi​计算。复杂度为 O ( n ) O(n) O(n)。

#include<bits/stdc++.h>using namespace std;int n, m;
long long suma, sumb;int main() {scanf("%d%d", &n, &m);for (int i = 1, a; i <= n; i++)scanf("%d", &a), suma += a;for (int i = 1, b; i <= m; i++)scanf("%d", &b), sumb += b;printf("%lld\n", suma * sumb);return 0;
}
  1. 谁是中间的那个(15 分)
    题目描述:一天,农夫乔伊像往常一项来到了他的农场,他突然对他的奶牛的产量产生了兴趣。他想知道产奶量处于中间的那头奶牛的产奶量是多少。“处于中间的”意思是说,其中有一半牛的产奶量比它多,另一半牛的产奶量比它少。
    现在由你来完成这个问题的程序。
    输入格式:仅包括一组测试数据,第一行一个正整数 N ( 1 ≤ N ≤ 10000 ) N \ (1≤N≤10000) N (1≤N≤10000),接下来 N N N 行,每行一个正整数,不会超过 1 0 6 10^6 106,第 i + 1 i+1 i+1 行的数字代表第 i i i 头牛的产奶量。
    输出格式:输出处于中间的牛的产奶量。
输入样例:
5
1
2
3
4
5
输出样例:
3

“其中有一半牛的产奶量比它多,另一半牛的产奶量比它少”这句话不是很严谨,但是很明显是排序后输出中间的数,复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)。

#include<bits/stdc++.h>using namespace std;
const int N = 10010;
int n, a[N];int main() {scanf("%d", &n);for (int i = 1; i <= n; i++)scanf("%d", &a[i]);sort(a + 1, a + n + 1);printf("%d\n", a[(n + 1) / 2]);return 0;
}

另外,借助快速排序的思想,只需要 O ( n ) O(n) O(n)的时间就可以求出第 k k k小的数。
每次选取基准值后,我们可以统计出小于等于基准值的数的数量 c n t cnt cnt,如果 k = c n t + 1 k=cnt+1 k=cnt+1,那么基准值就是第 k k k小的数;如果 k < c n t + 1 k<cnt+1 k<cnt+1,我们就在左半段(小于或等于基准值的数中)寻找第 k k k小的数;如果 k > c n t + 1 k>cnt+1 k>cnt+1,我们就在右半段(比基准值大的数中)寻找第 k − ( c n t + 1 ) k-(cnt+1) k−(cnt+1)小的数。因此,寻找第k小的数时,我们只需要进入左右两半二者之一继续递归。
在平均情况下,复杂度为 n + n 2 + n 4 + ⋯ + 1 = O ( n ) n+\frac{n}{2}+\frac{n}{4}+\dots+1=O(n) n+2n​+4n​+⋯+1=O(n)。
为防止复杂度退化至 O ( n 2 ) O(n^2) O(n2),最好给每一个数附加一个随机的权值,并且在待查找区间中随机选择基准值。

#include<bits/stdc++.h>using namespace std;
const int N = 10010;
int n;
pair<int, int> a[N];int solve(int l, int r, int k) {if (l == r)return a[l].first;int x = l, y = r, p = l + rand() % (r - l + 1);while (x < y) {while (a[p] < a[y])y--;swap(a[y], a[p]), p = y;while (x < y && a[x] <= a[p])x++;swap(a[x], a[p]), p = x;}if (p - l + 1 == k)return a[l + k - 1].first;if (p - l + 1 > k)return solve(l, p - 1, k);return solve(p + 1, r, k - (p - l + 1));
}int main() {srand((unsigned) time(0));scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i].first);a[i].second = rand();}printf("%d\n", solve(1, n, (n + 1) / 2));return 0;
}
  1. Doubles(15 分)
    题目描述:给出 2 2 2 到 15 15 15 个不同的正整数,计算在这些数里面有多少数据对满足一个数是另一个数的的两倍。比如给出:
    1 1 1 4 4 4 3 3 3 2 2 2 9 9 9 7 7 7 18 18 18 22 22 22
    答案是 3 3 3,因为 2 2 2 是 1 1 1 的两倍, 4 4 4 是 2 2 2 的两倍, 18 18 18 是 9 9 9 的两倍。
    输入格式:输入包括多组测试数据。每组测试数据包括一行,给出 2 2 2 到 15 15 15个两两不同且大于 0 0 0 小于 1000000 1000000 1000000 的正整数。每一行的最后一个数是 0 0 0,表示这一行的结束。输入的最后一行只包括一个整数 − 1 -1 −1,这行表示输入数据的结束,不用进行处理。
    输出格式:对于每组测试数据,输出一行,给出有多少个数对满足其中一个
    数是另一个数的两倍。
输入样例:
1 4 3 2 9 7 18 22 0
2 4 8 10 0
7 5 11 13 1 3 0
-1
输出样例:
3
2
0

和16年的题有重复,这里给出 O ( n ) O(n) O(n)的做法。

#include<bits/stdc++.h>using namespace std;
const int N = 1000010;
int a[N];
unordered_map<int, int> cnt;int main() {while (scanf("%d", &a[1]), a[1] != -1) {int n = 1;while (scanf("%d", &a[n + 1]), a[n + 1])n++;long long ans = 0;cnt.clear();for (int i = 1; i <= n; i++) {ans += cnt[a[i] * 2];if (a[i] % 2 == 0)ans += cnt[a[i] / 2];cnt[a[i]]++;}printf("%lld\n", ans);}return 0;
}
  1. Power Strings(30 分)
    题目描述:给出两个字符串 a a a 和 b b b,我们定义 a ∗ b a*b a∗b 为它们的毗连。例如,如果 a a a=”abc”并且 b b b=”def”,那么 a ∗ b a*b a∗b=”abcdef”。如果我们把毗连视为乘法,那么非负整数的指数定义为: a 0 = a^0= a0=””(空串), a ( n + 1 ) = a ∗ ( a n ) a^{(n+1)}=a*(a^n) a(n+1)=a∗(an)。
    输入格式:输入包含多个测试用例。每个测试用例是一个可打印字符的组成的字符串 s s s。 s s s 的长度至少是 1 1 1,不超过 1 百万个字符。输入的最后一行是是一个句号,表示输入数据的结束,不用处理。
    输出格式:对于每组测试数据,输出一行,对于字符串 s s s 输出最大的 n n n,使得对于某个字符串 a a a, s = a n s=a^n s=an。
输入样例:
abcd
aaaa
.
输出样例
1
4

设字符串长度为 n n n,从小到大枚举循环节的长度 i i i,如果 n m o d i = 0 n\mod i=0 nmodi=0,则检查 i i i是否合适,如果合适输出 n / i n/i n/i。
由于数据规模是 1 0 6 10^6 106,为了防止超时,采用字符串哈希算法减少字符串比较的时间。同时只枚举 [ 1 , n ] [1 ,\sqrt n] [1,n ​]范围内的循环节长度,顺便找到 [ n , n ] [\sqrt n,n] [n ​,n]范围内要枚举的循环节长度,把枚举循环节的复杂度降低至 O ( n ) O(\sqrt n) O(n ​)。最终时间复杂度应当远小于 O ( n n ) O(n\sqrt n) O(nn ​),实测完全可行。

#include<bits/stdc++.h>#define ull unsigned long long
using namespace std;
const int N = 1e6 + 10;struct Hash {const int base = 131;ull h[N], p[N];inline ull get(int l, int r) {return h[r] - h[l - 1] * p[r - l + 1];}inline void init(char *a) {int n = strlen(a + 1);p[0] = 1;for (int i = 1; i <= n; i++) {h[i] = h[i - 1] * base + a[i] - 'a' + 1;p[i] = p[i - 1] * base;}}
} H;char a[N];
int n;
vector<int> tmp;inline bool check(int x) {ull cmp = H.get(1, x);for (int i = x + 1; i + x - 1 <= n; i += x)if (H.get(i, i + x - 1) != cmp)return false;return true;
}int main() {while (scanf("%s", a + 1), a[1] != '.') {H.init(a);n = strlen(a + 1);int ans = 0;tmp.clear();for (int i = 1; i <= sqrt(n); i++)if (n % i == 0) {tmp.push_back(n / i);if (check(i)) {ans = n / i;break;}}if (!ans)for (int i = tmp.size() - 1; i >= 0; i--)if (check(tmp[i])) {ans = n / tmp[i];break;}printf("%d\n", ans);}return 0;
}

根据前缀函数的性质可以 O ( n ) O(n) O(n)复杂度求出。
对于字符串 s s s和 0 < p ≤ ∣ s ∣ 0<p\le|s| 0<p≤∣s∣,若 s [ i ] = s [ i + p ] s[i]=s[i+p] s[i]=s[i+p]对于 i ∈ [ 1 , ∣ s ∣ − p ] i\in[1,|s|-p] i∈[1,∣s∣−p]成立,则称 p p p是 s s s的周期。
对字符串 s s s和 0 ≤ r ≤ ∣ s ∣ 0\le r\le|s| 0≤r≤∣s∣,若 s s s长度为 r r r的前缀和长度为 r r r的后缀相等,就称 s s s长度为 r r r的前缀是 s s s的 b o r d e r border border。
由 s s s有长度为 r r r的 b o r d e r border border可以推导出 ∣ s ∣ − r |s|-r ∣s∣−r是 s s s的周期。
根据前缀函数的定义,可以得到 s s s所有的 b o r d e r border border长度,即 N e x t [ n ] , N e x t [ N e x t [ n ] ] , N e x t [ N e x t [ N e x t [ n ] ] ] , … Next[n],Next[Next[n]],Next[Next[Next[n]]],\dots Next[n],Next[Next[n]],Next[Next[Next[n]]],…
最终答案为总长度 n n n除以能被 n n n整除的最小周期。
由于前缀函数可以 O ( n ) O(n) O(n)复杂度求出,因此时间复杂度为 O ( n ) O(n) O(n)。

#include<bits/stdc++.h>using namespace std;
const int N = 1e6 + 10;char a[N];
int n, Next[N];void build_next() {for (int i = 2, j = 0; i <= n; i++) {while (j && a[i] != a[j + 1])j = Next[j];if (a[i] == a[j + 1])j++;Next[i] = j;}
}int main() {while (scanf("%s", a + 1), a[1] != '.') {n = strlen(a + 1);build_next();printf("%d\n", n % (n - Next[n]) ? 1 : n / (n - Next[n]));}return 0;
}
  1. 循环有序序列(30 分)
    题目描述:定义一种循环有序序列,该序列可看做首尾相连的圈状序列,从某个位置开始向后数至该位置的前一位,数过的元素都是从小到大排列的。例如,对于 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4这四个数,符合条件的循环有序序列有 1 , 2 , 3 , 4 ; 2 , 3 , 4 , 1 ; 3 , 4 , 1 , 2 ; 4 , 1 , 2 , 3 1,2,3,4; 2,3,4,1; 3,4,1,2; 4,1,2,3 1,2,3,4;2,3,4,1;3,4,1,2;4,1,2,3 四个。
    定义一种操作,可以在序列里任选一个位置的数,把它移动到序列的第一个位置,例如序列 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4,对 3 3 3 进行操作后,序列变为 3 , 1 , 2 , 4 3,1,2,4 3,1,2,4。
    现在输入一个长度为 n n n 的初始序列,问至少经过多少次操作,可以使原序列变成一个循环有序序列。
    输入格式:输入数据包含若干测试用例。每个测试用例的格式为:第 1 1 1 行:一个整数 N N N ( 1 ≤ N ≤ 30000 ) (1≤N≤30000) (1≤N≤30000);第 2 2 2 行: N N N 个整数 a i a_i ai​, ( 1 ≤ a i ≤ N ) (1≤a_i≤N) (1≤ai​≤N),并且对于任意的 i ≠ j i≠j i​=j, a i ≠ a j a_i≠a_j ai​​=aj​。输入的最后一行为 0,表示输入结束,不需要做处理。
    输出格式:对每个测试用例,输出一行,该行包括一个整数,表示至少需要的操作次数。
输入样例:
4
3 2 4 1
0
输出样例:
1

说明:对于序列 3 , 2 , 4 , 1 3,2,4,1 3,2,4,1,只需要做一次操作,得到 2 , 3 , 4 , 1 2,3,4,1 2,3,4,1 即是循环有序序列。
显然是要找到当前序列的子序列中长度最大的循环有序序列,然后剩余元素移到开头一定能使整个序列变成成循环有序序列且操作数最少。
设 d p [ i ] dp[i] dp[i]表示当前以 i i i为结尾的子序列中可构成的循环有序序列中最大的长度,初始为 0 0 0。遍历序列,对于当前遍历到的序列中的数 x x x,更新 d p [ x ] = d p [ ( n + x − 2 ) m o d n + 1 ] + 1 dp[x] = dp[(n + x - 2) \mod n + 1] + 1 dp[x]=dp[(n+x−2)modn+1]+1。
最后答案为 n − max ⁡ i = 1 n d p [ i ] \ n-\max\limits_{i=1}^{n}dp[i]  n−i=1maxn​dp[i]。时间复杂度为 O ( n ) O(n) O(n)。

#include<bits/stdc++.h>using namespace std;
const int N = 3e4 + 10;
int n, dp[N];int main() {while (scanf("%d", &n), n) {memset(dp, 0, sizeof(int) * n);for (int i = 1, x; i <= n; i++) {scanf("%d", &x), x--;dp[x] = dp[(x - 1 + n) % n] + 1;}printf("%d\n", n - *max_element(dp, dp + n));}return 0;
}

2017 年实验班选拔试题相关推荐

  1. 2016 年实验班选拔试题

    SUM(10 分) 题目描述:求出在 1 到 N 之间的所有整数的总和. 输入格式:输入包含多组测试数据.每行是一组测试数据,该数据是一个绝对值不 大于 10000 的整数 N.N=0 时,表示输入结 ...

  2. 北大2017计算机期末考试试题,北京大学2017年自主招生测试题汇总

    北京大学2017年自主选拔项目--自主招生.博雅人才培养计划.筑梦计划的测试于11日至14日进行,同时开始的还有浙江省"三位一体"综合评价和上海市"博雅计划"招 ...

  3. html二级选择题,2017计算机二级考试试题web习题及答案

    2017计算机二级考试试题web习题及答案 古话说得好"读书破万卷,下笔如有神",只有积累了一定的经验,才可能提炼出思维的规律,下面是百分网小编为大家整理的2017计算机二级考试试 ...

  4. 2017计算机软件考试试题,2017年计算机应用考试试题含答案.doc

    文档介绍: 2017年计算机应用考试试题含答案.doc2017年计算机应用考试试题含答案 2017年计算机应用考试试题(含答案) 一.单项选择题 1.下列关于软件的叙述中,正确的是 . A.计算机软件 ...

  5. 2017一季度JAVA面试题锦集

    转载自 2017一季度JAVA面试题锦集 1.如何实现分布式事务,你们公司是怎么解决的? 2.HashMap数据结构及实现原理,其链表是用来解决什么问题的 3.可以自定义java.lang.Strin ...

  6. 日常计算机操作知识试题,关于2017计算机一级考试试题操作题

    关于2017计算机一级考试试题操作题 在日常学习和工作中,我们很多时候都不得不用到试题,试题可以帮助参考者清楚地认识自己的知识掌握程度.那么一般好的试题都具备什么特点呢?下面是小编为大家整理的关于20 ...

  7. 计算机应用基础考试试题,2017计算机应用基础考试试题及答案

    2017计算机应用基础考试试题及答案 一.判断题 1. 在word2003中,间距是指所选定段落中行与行之间的距离.(F ) 2. 在Word中,使用鼠标拖放的方法,可以复制文本,也可以移动文本.( ...

  8. c 语言编译程序的首要工作,2017年计算机基础试题选择题「附答案」

    2017年计算机基础试题选择题「附答案」 一.单项选择题(每题1.5分,共30分) 1.操作系统是一种(a) A.系统软件 B.系统程序库 C.编译程序系统 D.应用软件 2.下列几种存储器中,存取速 ...

  9. 中央电大计算机网络试题,2017电大统考计算机试题及答案

    2017电大统考计算机试题及答案 A:"Internet时间"标签按钮 B:"日期"标签按钮 C:"时间"标签按钮 D:"时区&q ...

最新文章

  1. 科普:浅谈 Hellinger Distance
  2. UVa-442-Matrix Chain Multiplication
  3. android application常见错误
  4. JAVA调用SQL存储过程详解
  5. boost::python模块实现使用任意 Python 序列创建 ndarray 的示例
  6. Linux 搜狗输入法 候选字乱码
  7. mcq 队列_MCQ | 密码学中作为IDEA,DES,AES,RSA的块密码
  8. java 获取键盘输入法_Java中接收键盘输入的三种方法
  9. 机器学习项目实战----新闻分类任务(一)
  10. bt种子文件文件结构
  11. 8.1.CentOS7安装Spark安装部署及standalone模式介绍
  12. 水印相机定位不准确怎么办_水印相机怎么定位位置
  13. W10计算机策略怎么打开,如何打开组策略,详细教您win10如何打开组策略
  14. ws550 第三方固件_【详细图文】华为WS550固件升级方法
  15. Material design - 色彩样式(一)
  16. msm8953 PWM背光
  17. macOS通过单个typeC拓展坞连接多台显示器实现多屏幕拓展(多屏异显)解决typeC拓展坞只能多屏镜像
  18. 人工智能数学基础--微分:定义、运算以及应用
  19. 传输层端口、TCP和UDP的概念
  20. ArcGIS 图层上点的编辑

热门文章

  1. 解开最后期限的镣铐(转载)
  2. 【Python游戏】用Python实现一个测试你智商的小游戏——24点,过不了三关的都是细狗 | 附带源码
  3. mysql源码分析——索引的数据结构
  4. linux修改php环境变量
  5. java基本数据类型长度详解
  6. Sencha-组件-Chart(图表)(官网文档翻译17)
  7. h5调用本地摄像头和麦克风一
  8. 聊一聊平时常用的加密算法
  9. 测试修改和删除用户的功能
  10. 利用WordPress 模板建站,如果利用阿里云国际版获取网站高流量