2016 年实验班选拔试题

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

求和公式

#include<bits/stdc++.h>

using namespace std;
int n;

int main() {
    while (scanf("%d", &n), n)
        printf("%d\n", (1 + n) * (abs(n - 1) + 1) / 2);
    return 0;
}
  1. Doubles(20 分)
    题目描述:给出 2 到 15 个不同的正整数,计算在这些数里面有多少对数据满足一个
    数是另一个数的两倍。比如给出:
    1 4 3 2 9 7 18 22
    答案是 3。因为 2 是 1 的两倍,4 是 2 的两倍,18 是 9 的两倍。
    输入格式:输入包含多组测试数据。每组测试数据包括一行,给出 2 到 15 个两两不
    同且大于 0 小于 1000000 的正整数。每一行的最后一个数是 0,表示这一行的结束。输
    入的最后一行只包括一个整数-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 

由于数据规模较小,直接枚举所有情况,复杂度为O(n2)O(n^2)

#include<bits/stdc++.h>

using namespace std;
const int N = 20;
int a[N];

int main() {
    while (scanf("%d", &a[1]), a[1] != -1) {
        int n = 1;
        while (scanf("%d", &a[n + 1]), a[n + 1])n++;
        int cnt = 0;
        for (int i = 1; i < n; i++)
            for (int j = i + 1; j <= n; j++)
                if (a[i] == a[j] * 2 || a[i] * 2 == a[j])cnt++;
        printf("%d\n", cnt);
    }
    return 0;
}

假如数据规模达到了10610^6,可以对于每个数xx,找这个数之前等于2x2·xx/2x/2的个数求和即可,复杂度为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. Count(30 分)
    题目描述:输入一组单词,输出指定单词的出现次数。
    输入格式:输入数据包含若干测试用例,每个测试用例的格式为:第一行:N;第二
    行:N 个单词,相邻单词用一个空格间隔;第三行:指定单词。当读到 N=0 时输入结
    束。其中 N 不超过 1000,每个单词长度不超过 10,仅字母大小写有区别的单词认为是
    同一个单词。
    输出格式:对于每个测试用例,输出指定单词的出现次数。
输入样例:
3
ACM ICPC TEACHING 
ICPC
2
TEACHING research
ACM
5
Teaching ACM RESEARCH aCm Acm
ACM
0
输出样例:
1
0
3 

利用stl中的map统计个数即可。

#include<bits/stdc++.h>

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

int main() {
    while (scanf("%d", &n), n) {
        cnt.clear();
        string s;
        for (int i = 1; i <= n; i++) {
            cin >> s;
            int l = s.size();
            for (int j = 0; j < l; j++)if (s[j] >= 'A' && s[j] < 'Z')s[j] += 'a' - 'A';
            cnt[s]++;
        }
        cin >> s;
        int l = s.size();
        for (int j = 0; j < l; j++)if (s[j] >= 'A' && s[j] < 'Z')s[j] += 'a' - 'A';
        printf("%d\n", cnt[s]);
    }
    return 0;
}
  1. Error Correction(30 分)
    Description
    A boolean matrix has the parity property when each row and each column has an
    even sum, i.e. contains an even number of bits which are set. Here’s a 4 x 4 matrix which
    has the parity property:
1 0 1 0
0 0 0 0
1 1 1 1
0 1 0 1

The sums of the rows are 2, 0, 4 and 2. The sums of the columns are 2, 2, 2 and 2.
Your job is to write a program that reads in a matrix and checks if it has the parity
property. If not, your program should check if the parity property can be established by
changing only one bit. If this is not possible either, the matrix should be classified as
corrupt.
Input
The input will contain one or more test cases. The first line of each test case contains
one integer n (n<100), representing the size of the matrix. On the next n lines, there will
be n integers per line. No other integers than 0 and 1 will occur in the matrix. Input will
be terminated by a value of 0 for n.
Output
For each matrix in the input file, print one line. If the matrix already has the parity
property, print “OK”. If the parity property can be established by changing one bit, print
“Change bit (i,j)” where i is the row and j the column of the bit to be changed. Otherwise,
print “Corrupt”.

Sample Input
4
1 0 1 0
0 0 0 0
1 1 1 1
0 1 0 1
4 
1 0 1 0
0 0 1 0
1 1 1 1
0 1 0 1
4
1 0 1 0
0 1 1 0
1 1 1 1
0 1 0 1
0
Sample Output
OK
Change bit (2,3)
Corrupt 

统计各行各列的和,如果均为偶数,则输出"OK";如果仅有一个行ii和一个列jj和为奇数,则输出"Change bit (i,j)";其他情况输出"Corrupt "。

#include<bits/stdc++.h>

using namespace std;
const int N = 105;
int row[N], col[N], n;

int main() {
    while (scanf("%d", &n), n) {
        for (int i = 1; i <= n; i++)row[i] = col[i] = 0;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++) {
                int x;
                scanf("%d", &x);
                if (x)row[i]++, col[j]++;
            }
        bool suc = true;
        int x = 0, y = 0;
        for (int i = 1; i <= n; i++) {
            if (row[i] % 2) {
                if (x) {
                    suc = false;
                    break;
                }
                x = i;
            }
            if (col[i] % 2) {
                if (y) {
                    suc = false;
                    break;
                }
                y = i;
            }
        }
        if (!x && !y)puts("OK");
        else if (suc && x && y)printf("Change bit (%d,%d)\n", x, y);
        else puts("Corrupt");
    }
    return 0;
}
  1. 回文词(50 分)
    题目描述:回文词是一种对称的字符串,即一个字符串从左向右读和从右向左读是
    等同的。任意给出一个字符串,通过插入若干个字符,都可以变成回文词。本题的任务
    是,求出将给定字符串变成回文词所需要插入的最少字符数。
    比如“Ab3bd”插入两个字符后 可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入
    少于两个的字符无法变成回文词。
    输入格式:输入数据由多组测试用例组成。每组测试用例包含两行输入,第一行是
    一个整数,表示输入的字符串长度 N,3<=N<=5000;第二行给出长度为 N 的字符串。
    字符串由 A 到 Z 的大写字母,a 到 z 的小写字母和从 0 到 9 的数字组成。本问题区分大
    小写。当 N=0 时,表示输入结束。
    输出格式:对于每一组测试数据,输出一个整数,是所要求的最小数。
输入样例
5
Ab3bd
0
输出样例
2 

原字符串与其翻转后的串求最长公共子序列,用字符串的长度减去最长公共子序列的长度即为答案。

#include<bits/stdc++.h>

using namespace std;
const int N = 5005;
int dp[N][N], n;
char a[N], b[N];

int main() {
    while (scanf("%d", &n), n) {
        scanf("%s", a + 1);
        memcpy(b, a, sizeof(a));
        reverse(b + 1, b + n + 1);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++) {
                if (a[i] == b[j])dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        printf("%d\n", n - dp[n][n]);
    }
    return 0;
}

一个小技巧,利用滚动数组可以将二维的dpdp数组压缩成一维,节省空间。

#include<bits/stdc++.h>

using namespace std;
const int N = 5005;
int dp[2][N], n;
char a[N], b[N];

int main() {
    while (scanf("%d", &n), n) {
        scanf("%s", a + 1);
        memcpy(b, a, sizeof(a));
        reverse(b + 1, b + n + 1);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++) {
                if (a[i] == b[j])dp[i & 1][j] = dp[i - 1 & 1][j - 1] + 1;
                else dp[i & 1][j] = max(dp[i - 1 & 1][j], dp[i & 1][j - 1]);
            }
        printf("%d\n", n - dp[n & 1][n]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章