【题目自解】北京大学2017计算机学科夏令营上机考试

【题目自解】北京大学2017计算机学科夏令营上机考试

A:判决素数个数 (NOI 1.13编程基础之综合应用)

解题思路

两个坑,一个是x,y大小关系不确定,要写一个交换;一个是取值范围可以到100000,因此i*i到了十位数量级,在int表示中是负数(虽然我觉得没到int限制范围啊,但是测试结果确实是这样),这时候访问数组会报错。

如果继续用i*i,语句应该改为

for (int j = i * i; j <= N && j>0; j += i) mark[j] = 1;

AC代码(2*i版本)

#include<cstdio>
#include<cstring>
const int N = 100000;
int mark[N + 5] = { 0 };
int num = 0;

void Prime()
{
    mark[1] = 1;
    for (int i = 2; i <= N; i++)
    {
        if (mark[i] == 1)continue;
        for (int j = 2 * i; j <= N; j += i) mark[j] = 1;
    }
}

int main()
{
    int x, y;
    scanf("%d%d", &x, &y);
    if (x > y)
    {
        int t = y;
        y = x;
        x = t;
    }
    Prime();
    for (int i = x; i <= y; i++)
    {
        if (mark[i] == 0)num++;
    }
    printf("%d", num);
    return 0;
}

B:编码字符串

解题思路

简单题,直接做就行了。tolower的头文件是cctype,string里面也有。更简单的做法是边判断边输出。

解题代码

#include<cstdio>
#include<cstring>
#include<cctype>
char s[1005];
char c[1005];//存储字符
int n[1005];//存储每个字符的数量
int cnt = 0;//分割段数-1

int main()
{
    scanf("%s", s);
    int len = strlen(s);
    for (int i = 0; i < len; i++)s[i] = tolower(s[i]);
    c[0] = s[0];//初始化
    memset(n, 0, sizeof(n));
    n[0] = 1;
    for (int i = 1; i < len; i++)
    {
        if (s[i] == c[cnt])n[cnt]++;
        else
        {
            cnt++;
            c[cnt] = s[i];
            n[cnt]++;
        }
    }
    for (int i = 0; i <= cnt; i++)
    {
        printf("(%c,%d)", c[i], n[i]);
    }
    return 0;
}
#include <cstdio>
#include <cstring>
using namespace std;
 
int main()
{
    char buf[1001];
    scanf("%s",buf);
    int len=strlen(buf);
    int i;
    for(i=0;i<len;i++){
        if(buf[i]>='A'&&buf[i]<='Z'){
            buf[i]+=32;
        }
    }
    i=0;
    char tmp;
    int cnt;
    while(i<len){
        tmp=buf[i];
        cnt=0;
        while(buf[i]==tmp){
            i++;
            cnt++;
        }
        printf("(%c,%d)",tmp,cnt);
    }
    printf("
");
    return 0;
}
变判断边输出

C:岛屿周长

解题思路

简单题,深搜遍历上下左右的点,如果是海或者是边界,那么周长++。

AC代码

#include<cstdio>
#include<cstring>

int map[105][105];
int mark[105][105] = { 0 };
int n, m;
int len = 0;
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };

bool valid(int x,int y)
{
    return(x >= 0 && x < n && y >= 0 && y < m);
}

void DFS(int x,int y)
{
    mark[x][y] = 1;
    for (int i = 0; i < 4; i++)
    {
        int newx = x + dx[i];
        int newy = y + dy[i];
        if (valid(newx, newy))
        {
            if (mark[newx][newy] == 0) DFS(newx, newy);
        }
        else len++;
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++) scanf("%d", &map[i][j]);
    }
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            if (mark[i][j] == 1 || map[i][j] == 0)continue;
            DFS(i, j);
        }
    }
    printf("%d", len);
    return 0;
}

E:怪盗基德的滑翔翼

解题思路

简单题,因为可以任选一个方向,所以是正反都要做一次最长不上升子序列,等价于正序找最长不上升子序列和最长不下降子序列,然后取较大值。

AC代码

#include<cstdio>

const int N = 105;
int a[N];//记录原序列
int dp[N];//dp[i]表示包括第i位之前序列的最长上升子序列长度
int len;//原序列长度

int LIS()
{
    int tmp = 1;//返回值,表示整个序列的LIS值
    for (int i = 1; i <= len; i++)
    {
        dp[i] = 1;//都初始化为1,方便后面直接比较
        for (int j = 1; j < i; j++)
        {
            if (a[j] <= a[i] && dp[j] + 1 > dp[i]) dp[i] = dp[j] + 1;
        }
        if (dp[i] > tmp) tmp = dp[i];
    }
    return tmp;
}

int RLIS()
{
    int tmp = 1;//返回值,表示整个序列的RLIS值
    for (int i = 1; i <= len; i++)
    {
        dp[i] = 1;//都初始化为1,方便后面直接比较
        for (int j = 1; j < i; j++)
        {
            if (a[j] >= a[i] && dp[j] + 1 > dp[i]) dp[i] = dp[j] + 1;
        }
        if (dp[i] > tmp) tmp = dp[i];
    }
    return tmp;
}


int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d", &len);
        for (int i = 1; i <= len; i++)scanf("%d", &a[i]);
        int a1 = LIS();
        int a2 = RLIS();
        int ans = a1 > a2 ? a1 : a2;
        printf("%d
", ans);
    }
    return 0;
}

G:实现堆结构

解题思路

使用优先队列。 

AC代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

priority_queue<int, vector<int>, greater<int> > q; // 小堆顶结构

int main()
{
    int t;
    scanf("%d", &t);
    for(int i=0; i<t; i++)
    {
        int n, type;
        scanf("%d", &n);
        for(int j=0; j<n; j++)
        {
            scanf("%d", &type);
            if(type == 1)
            {
                int u;
                scanf("%d", &u);
                q.push(u);
            }
            if(type == 2)
            {
                printf("%d
", q.top());
                q.pop();
            }
        }
    }
    return 0;
}

D:Safecracker

解题思路

可以用五层循环,也可以用dfs。

AC代码(五层循环暴搜解法)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

int toInt(char ch) 
{
    return ch - 'A' + 1;
}

int target;
char a[15];
int main() 
{
    while (scanf("%d%s", &target, a) && (target != 0 || strcmp(a, "END") != 0)) {
        sort(a, a + strlen(a));
        int sum;
        int flag = 0;
        string str;
        for (int i = 0; a[i]; i++) {
            for (int j = 0; a[j]; j++) {
                for (int k = 0; a[k]; k++) {
                    for (int l = 0; a[l]; l++) {
                        for (int m = 0; a[m]; m++) {
                            if (i != j && i != k && i != l && i != m && j != k &&
                                j != l && j != m && k != l && k != m && l != m) {
                                sum = toInt(a[i]) - toInt(a[j]) * toInt(a[j]) + toInt(a[k]) *toInt(a[k]) *
                                    toInt(a[k]) - toInt(a[l]) *toInt(a[l]) * toInt(a[l]) *toInt(a[l]) + toInt(a[m]) *
                                    toInt(a[m]) *toInt(a[m]) *toInt(a[m]) * toInt(a[m]);
                                if (sum == target) {
                                    flag = 1;
                                    str = "";
                                    str = str + a[i] + a[j] + a[k] + a[l] + a[m];
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        if (flag == 1) {
            printf("%s
", str.c_str());
        }
        else printf("no solution
");
    }
    return 0;
}

AC代码(DFS解法)

#include <iostream>
#include <cstring>

using namespace std;

int n;
int len;
char s[15];//存放原字符串
int vis[15];//深搜访问标记
int t[5];//存放最终字符串
int p[5];//转换后的数字

void check()//更新为最大字典序
{
    for (int i = 0; i < 5; i++)
    {
        if (p[i] > t[i])
        {
            for (int j = 0; j < 5; j++)
            {
                t[j] = p[j];
            }
            break;
        }
        if (p[i] < t[i])
        {
            break;
        }
    }
}

void dfs(int cur)
{
    if (cur == 5)
    {
        if (n == p[0] - p[1] * p[1] + p[2] * p[2] * p[2] - p[3] * p[3] * p[3] * p[3] + p[4] * p[4] * p[4] * p[4] * p[4])
        {
            check();
        }
    }
    else
    {
        for (int i = 0; i < len; i++)//逐元素向前推进进行深搜
        {
            if (!vis[i])
            {
                vis[i] = 1;
                p[cur] = s[i] - 'A' + 1;
                dfs(cur + 1);
                vis[i] = 0;//回溯
            }
        }
    }
}

int main()
{
    while (true)
    {
        cin >> n >> s;
        if (n == 0)
        {
            return 0;
        }
        len = strlen(s);
        memset(vis, 0, sizeof(vis));
        memset(t, 0, sizeof(t));
        memset(p, 0, sizeof(p));
        dfs(0);
        if (t[0] == 0)
        {
            cout << "no solution" << endl;
        }
        else
        {
            for (int i = 0; i < 5; i++)
            {
                cout << (char)(t[i] + 'A' - 1);
            }
            cout << endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yun-an/p/11108072.html