2016-2017-1学期2013信息与计算科学12班<算法分析与设计>期末测试
Problem ID | Title | Source |
---|---|---|
1183 | Problem A 公约数和公倍数 | 基础 |
1268 | Problem B 逆反A*B | icpc4th@ahstu |
1426 | Problem C 子串和 | NYOJ |
1264 | Problem D 图书馆占位 | icpc4th@ahstu |
1527 | Problem E 快看,有人捡到钱了!!! | wwy |
1528 | Problem F 蚂蚁 | nyoj |
1529 | Problem G 寻找最大数 | nyoj改编 |
1530 | Problem H 神童的烦恼 | nyoj改编 |
1531 | Problem I Grasshopper | Codeforces改编 |
Problem A 公约数和公倍数
Description
小明被一个问题给难住了,现在需要你帮帮忙。问题是:给出两个整数,求出它们的最大公约数和最小公倍数。
Input
第一行输入一个大于0的整数n(n<=20),示有n组测试数据随后的n行输入两个整数i,j(i,j小于32767)。
Output
输出每组测试数据的最大公约数和最小公倍数
Sample Input
3
6 6
12 11
33 22
Sample Output
6 6
1 132
11 66
题解:这道题属于简单题,下面直接给出代码
#include <stdio.h>
int gcd(int a, int b)
{
return b ? gcd(b, a%b) : a;
}
int main()
{
int t, a, b;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &a, &b);
printf("%d %d
", gcd(a, b), a*b/gcd(a, b));
}
return 0;
}
Problem B 逆反A*B
Description
给定A B计算A*B的结果C,不过这里面都要反过来啦!
举例:52*52=526 因为52表示25(逆反数)25*25=652,
A B 不超过10000
Input
输入A,B
Output
计算A B的逆反数的积的逆反数C
Sample Input
52 52
30 30
1 1
Sample Output
526
9
1
题解:这道题也是道简单题,详见代码,关键写一个逆反数的转换函数即可
#include <stdio.h>
int f(int n,int a)
{
return n?f(n/10,a*10+n%10):a;
}
int main()
{
int a,b;
while(~scanf("%d%d",&a,&b))
printf("%d
",f(f(a,0)*f(b,0),0));
return 0;
}
Problem C 子串和
Description
给定一整型数列{a1,a2…,an},找出连续非空子串{ax,ax+1,…,ay},使得该子序列的和最大,其中,1<=x<=y<=n。
Input
第一行是一个整数N(N<=10)表示测试数据的组数)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的一行里有n个整数I(-100=
Output
对于每组测试数据输出和最大的连续子串的和。
Sample Input
1
5
1 2 -1 3 -2
Sample Output
5
Hint
输入数据很多,推荐使用scanf进行输入
题解:经典算法,对数列进行一次扫描并求和,保存其thisSum,并更新最大和maxSum,若是当前和thisSum<0,则置thisSum=0从当前位置开始累加,因为负数加上一个数肯定是会变小的,最终的maxSum就是最大值
#include <stdio.h>
int main()
{
int T, n, x;
scanf("%d", &T);
while(T--)
{
int thisSum=0, maxSum=0;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%d", &x);
thisSum += x;
if(thisSum > maxSum)
maxSum = thisSum;
if(thisSum < 0)
thisSum = 0;
}
printf("%d
", maxSum);
}
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while (t-- > 0) {
int n = cin.nextInt();
int maxSum = 0, thisSum = 0;
for (int i=0; i<n; i++) {
int data = cin.nextInt();
thisSum += data;
if (thisSum > maxSum)
maxSum = thisSum;
if (thisSum < 0)
thisSum = 0;
}
System.out.println(maxSum);
}
cin.close();
}
}
Problem D 图书馆占位
Description
图书馆占位的很厉害,只要去晚了一会就没有位置了。有些人占着位置却不来自习,这就造成了资源的浪费。现在我们的问题是一天当中有n个同学可能会来到同一个座位,假设上面有人则另外找座位,若没有人,则就可以占据此位置,直至你离开为止。为了最大化利用图书馆资源,我们要求的问题是一个位置最多能够被几个同学来用过。
Input
多组测试数据
第一行为n个同学 (1 <=n<=10000)
接下来n行就是每个同学的进入图书馆的时间和离开图书馆的时间,为了简化问题,我们假设时间值为整数。
Output
输出一个座位最多被几位同学占据。
Sample Input
6
1 3
2 4
3 6
7 9
5 7
10 11
Sample Output
4
题解:此题用贪心法求解,首先对所有同学离开图书馆的先后进行排序,然后对此序列进行遍历,只要离开图书馆的时间小于第二个同学进入图书馆的时间,这个位置可坐人数+1,遍历完毕也即得到此位置最多可以容纳的人数
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct A {
int start, end;
bool operator<(const A &a) const {
return this->end < a.end;
}
};
int main() {
for (int n; cin >> n;) {
vector<A> v(n);
for (int i = 0; i < n; i++)
cin >> v[i].start >> v[i].end;
sort(v.begin(), v.end());
int tot = 0, start = 0;
for (vector<A>::iterator it = v.begin(); it != v.end(); ++it) {
if (it->start >= start) {
++tot;
start = it->end;
}
}
cout << tot << endl;
}
return 0;
}
Problem E 快看,有人捡到钱了!!!
Description
老赵喜欢吃烧烤,在一次和同学们吃完烧烤回来的路上,老赵一不小心捡了一百块,同学们强烈要求老赵买蛋糕庆祝,老赵爽快的扔了两百给蛋糕店,让他们做一个球形的大蛋糕。现在老赵拿起了刀叉准备和同学们瓜分这个蛋糕,一刀下去蛋糕成了两块,然后n个同学每人都来一刀。
现在老赵问同学们,n个人切完以后蛋糕最多有多少块。(能ac的送thinkpaid)。
Input
多组输入,每行一个整数n,n个同学
Output
对于每个整数n,输出一个整数s(n个人切完蛋糕最多有s块)
Sample Input
1
2
Sample Output
4
8
题解:这道题有一定难度,此题属于平面分割空间问题,需要运用递推关系,具体请查阅相关资料。
公式是f(n)=(n^3+5n)/6+1;
#include <stdio.h>
#include <math.h>
int main()
{
int n;
while (~scanf("%d",&n)) {
n++;
printf("%d
", (n*n*n+5*n)/6+1);
}
return 0;
}
Problem F 蚂蚁
Description
n只蚂蚁义每秒1cm的速度在长为Lcm的杆子上爬行。当蚂蚁爬到杆子的端点就会掉下去。由于杆子太细,两只蚂蚁相遇时,他们不能交错通过,只能各反向回去。对于每只蚂蚁,我们知道它距离杆子左端的距离xi,但不知道它当时的朝向,计算所有蚂蚁落下杆子的最短时间和最长时间。
1<=L<=10^6
1<=n<=10^6;
0<=xi<=L;
Input
多组输入,第一行L和n,接下来n个xi(L为杆子的长度,n只蚂蚁,及每只蚂蚁距离杆子左端的距离xi)
Output
输出蚂蚁落下杆子的最短时间和最长时间
Sample Input
10 3
2 6 7
Sample Output
4 8
题解:这道题只要考虑清楚后其实也很好解,不需要考虑掉头情况,因为蚂蚁速度一样,即是说蚂蚁掉头对此题不产生影响。也可以这样理解,在远处观察这些蚂蚁的运动,一群蚂蚁运动时,因为速度是一样的,所以当蚂蚁碰撞而掉头时,看上去和两个点“对穿而过”没有任何区别,这样,不论最长时间还是最短时间,都只要对每只蚂蚁检查一次就好了,这是O(n)时间的算法。于是问题得解。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
int L, n, minT, maxT, a;
while (~scanf("%d%d", &L, &n))
{
minT = 0; maxT = 0;
for (int i=0; i<n; i++) {
scanf("%d", &a);
minT = max(minT, min(a, L-a));
maxT = max(maxT, max(a, L-a));
}
printf("%d %d
", minT, maxT);
}
return 0;
}
Problem G 寻找最大数
Description
给出一个整数n每次可以移动相邻数位上的数字,最多移动k次,得到一个新的整数,求这个新的整数的最大值是多少。
Input
多组测试数据。
每组测试数据占一行,每行有两个数N和K (1 ≤ N≤ 10^18; 0 ≤ K ≤ 100).
Output
每组测试数据的输出占一行,输出移动后得到的新的整数的最大值。
Sample Input
1990 1
100 0
9090000078001234 6
Sample Output
9190
100
9907000008001234
题解:一个数交换每次相邻两位数,因为高位数字越大数字结果就越大。可以交换k次,所以可以依次在当前位置到当前的第k位找到最大数并交换到当前位置,每交换一次k–
重复上述步骤,直到k=0结束,这样得到数字也即使最大数
#include <stdio.h>
#include <string.h>
char a[100], max;
int k, i, j, index;
void solve()
{
int len = strlen(a);
for (i=0; i<len && k; i++) {
index = i; max = a[i];
for (j=i+1; j<len && j<=i+k; j++) {
if (max < a[j]) {
index = j;
max = a[j];
}
}
for (j=index; j>i; j--) {
a[j] = a[j-1];
k--;
}
a[i] = max;
}
puts(a);
}
int main()
{
while (~scanf("%s %d", a, &k))
{
solve();
}
return 0;
}
Problem H 神童的烦恼
Description
数学神童小明终于把0到100000000的Fibonacci数列(f[0]=0,f[1]=1;f[i] = f[i-1]+f=2”>i-2)的值全部给背了下来。
接下来,CodeStar决定要考考他,于是每问他一个数字,他就要把答案说出来,不过有的数字太长了。所以规定超过4位的只要说出前4位(高4位)就可以了,可是CodeStar自己又记不住。于是他决定编写一个程序来测验小明说的是否正确。
Input
输入若干数字n(0 <= n <= 100000000),每个数字一行。读到文件尾结束。
Output
输出f[n]的前4个数字(若不足4个数字,就全部输出)。
Sample Input
0
1
2
3
4
5
35
36
37
38
39
40
Sample Output
0
1
1
2
3
5
9227
1493
2415
3908
6324
1023
题解:这道题需要用到斐波那契数列的通项公式
log10f(n)=n*log10((1+√5)/2)-log10√5+log10(1-((1-√5)/(1+√5))n) 后一部分随着n的增大快速的就趋近余0,是高阶无穷小. 可以忽略。所以有log10f(n) ≈n*log10((1+√5)/2)-log10√5
此题要求斐波拉契前4位,由此可以得出pow(10,log10f(n)+3-整数部分),在对其取整即为结果。需要注意的是斐波拉契前较小项因为浮点误差所以应该事先求出
#include <stdio.h>
int main()
{
int n, i;
int fib[21]={0, 1};
for (i=2; i<=20; i++)
fib[i] = fib[i-1]+fib[i-2];
while (~scanf("%d", &n))
{
if (n <= 20)
printf("%d
", fib[n]);
else {
double f=n*log10((sqrt(5)+1)*.5)-log10(sqrt(5));
f = f+3-floor(f);
printf("%d
", (int)pow(10, f));
}
}
return 0;
}
Problem I Grasshopper
Description
One day, the Grasshopper was jumping on the lawn and found a piece of paper with a string. Grasshopper became interested what is the minimum jump ability he should have in order to be able to reach the far end of the string, jumping only on vowels of the English alphabet. Jump ability is the maximum possible length of his jump.
Formally, consider that at the begginning the Grasshopper is located directly in front of the leftmost character of the string. His goal is to reach the position right after the rightmost character of the string. In one jump the Grasshopper could jump to the right any distance from 1 to the value of his jump ability.
The picture corresponds to the first example.
The following letters are vowels: ‘A’, ‘E’, ‘I’, ‘O’, ‘U’ and ‘Y’.
Input
Input contains multiple test cases.The first line contains non-empty string consisting of capital English letters. It is guaranteed that the length of the string does not exceed 100.
Output
Print single integer a — the minimum jump ability of the Grasshopper (in the number of symbols) that is needed to overcome the given string, jumping only on vowels.
Sample Input
ABABBBACFEYUKOTT
AAA
Sample Output
4
1
题解:这道题是比较容易的一道题,主要是英语题于是大家都没有做了,思路很简单,找到一个序列中跨越元音字母(’A’, ‘E’, ‘I’, ‘O’, ‘U’, ‘Y’)的最大长度,看图例就能很好明白,直接给出代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
bool is(char c)
{
char a[6] = {'A', 'E', 'I', 'O', 'U', 'Y'};
for (int i=0; i<6; i++)
if (a[i] == c)
return true;
return false;
}
int main()
{
char s[1000];
while (~scanf("%s", s))
{
int m = 1, mx = 0;
for (int i=0; i<strlen(s); i++) {
if (is(s[i])) {
m = 1;
}else m++;
if (mx < m)
mx = m;
}
printf("%d
", mx);
}
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while (cin.hasNext()) {
char[] a = cin.next().toCharArray();
int len = 1, max = 1;
for (int i=0; i<a.length; i++) {
if (f(a[i])) {
len = 1;
}else
len++;
if (len > max)
max = len;
}
System.out.println(max);
}
cin.close();
}
private static boolean f(char c) {
char a[] = {'A', 'E', 'I', 'O', 'U', 'Y'};
for (int i=0; i<a.length; i++)
if (a[i] == c)
return true;
return false;
}
}