【题目自解】北京大学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("\n");
    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代码

猜你喜欢

转载自www.cnblogs.com/yun-an/p/11108072.html
今日推荐