第三届全国中医药院校大学生程序设计竞赛题解

A Welcome

题目描述

”How happy we are, To meet friends from afar!”
Welcome to Hunan University of Chinese Medicine!
Hope all of you can enjoy the competition ^ v ^
Now your task is to read an integer w and output the character painting of ”HNUCM”, there are w
space(s) (space are represented by dot) between two letters. Please refer to the sample for the specific
format.

输入

There are several test files and each contains one case.
The input contains only 1 integer w (1 ≤ w ≤ 2018).

输出

The output has 5 lines, each line has 25+4w characters which only contains ’o’(lowercase letter ’o’) and
’.’(English period ’.’)

样例输入 Copy

1

样例输出 Copy

o…o.o…o.o…o.ooooo.o…o
o…o.oo…o.o…o.o…oo.oo
ooooo.o.o.o.o…o.o…o.o.o
o…o.o…oo.o…o.o…o…o
o…o.o…o.ooooo.ooooo.o…o

这道题我找到了篇博客,写的更加简单:博客传送门

代码:

#include<bits/stdc++.h>
 
using namespace std;
string a="o...oo...ooooooo...oo...o";
string b="o...ooo..oo.o.oo..ooo...o";
string c="o...oo...oo...oo...oooooo";
string d="oooooo....o....o....ooooo";
string e="o...ooo.ooo.o.oo...oo...o";
 
int main(){
    int n;
    while(cin>>n){
        for(int i=0;i<5;i++){
        for(int j=0;j<5;j++) cout<<a[i*5+j];
        for(int j=0;j<n;j++) printf(".");
        for(int j=0;j<5;j++) cout<<b[i*5+j];
        for(int j=0;j<n;j++) printf(".");
        for(int j=0;j<5;j++) cout<<c[i*5+j];
        for(int j=0;j<n;j++) printf(".");
        for(int j=0;j<5;j++) cout<<d[i*5+j];
        for(int j=0;j<n;j++) printf(".");
        for(int j=0;j<5;j++) cout<<e[i*5+j];
 
        cout<<endl;
    }
    }
 
 
    return 0;
}

B 绿地装饰

在这里插入图片描述
输入

单组数据。
第一行两个数 N,K,如题意中的描述。
接下来是一个 N×N 的模板图,’ . ’ 表示白色,’ * ’ 表示黑色。
2 ≤ n ≤ 3
1 ≤ k ≤ 5

输出

输出一个 N K×N K 的矩阵表示答案,不允许有多余的空行或空格。

样例输入 Copy

2 3
.*

样例输出 Copy

.*******
…******
..*****
***
..***
*
....

代码:

#include<bits/stdc++.h>
 
using namespace std;
const int N=255;
int  n,k,m;
char a[N][N],c[N][N];
 
void bh(int x,int y,int siz){
    for(int i=0;i<siz;i++){
        for(int j=0;j<siz;j++){
            a[x+i][y+j]='*';
            //cout<<x+i<<",,"<<y+j<<endl;
        }
    }
}
 
void dfs(int x,int y,int siz){
 
    if(siz==1) return;      //当递归到最后一层,结束递归
    //cout<<"&1: "<<x<<" "<<y<<" "<<siz<<endl;
    //再次递归
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(c[i][j]=='*')
                bh(x+i*siz/n,y+j*siz/n,siz/n);      //左上角为 i*m/n,j*m/n,宽度为 m/n
            else
                dfs(x+i*siz/n,y+j*siz/n,siz/n);
        }
    }
 
 
}
 
int main(){
    cin>>n>>k;
    m=pow(n,k);       //整个矩阵的长宽
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cin>>c[i][j];
        }
    }
    memset(a,'.',sizeof a);    //初始化将所有设白色
 
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(c[i][j]=='*'){
 
                bh(i*m/n,j*m/n,m/n);      //左上角为 i*m/n,j*m/n,宽度为 m/n
            }
 
            else
                dfs(i*m/n,j*m/n,m/n);
        }
    }
 
    for(int i=0;i<m;i++){
        for(int j=0;j<m;j++){
            cout<<a[i][j];
        }
        cout<<endl;
    }
 
 
 
 
    return 0;
}

C 击鼓传花

题目描述

岳麓山下旌旗卷,新月湖畔起歌声。湖南中医药大学运动会隆重开幕了,小 Q 所在的班级参加了“击鼓
传花”趣味比赛。
比赛规则如下,n 个队员 (不包括小 Q) 围成一个圈,每个人手里拿着一些花束 (数量也可能为 0),小 Q
站在圆圈的中间,队员需要传递花束给小 Q,每个鼓点只允许一个人传送一束花,最终要求圆圈上所有
人的花束都传递给小 Q。请问需要花多少鼓点呢?

输入

多组数据。
第一行 n,代表队员数量。
第 2 行到第 n+1 行,每行一个整数 a[i],代表每个队员最开始拿的花束数量。
0 ≤ a[i] ≤ 106
所有组的 n 之和不超过 103

输出

一个整数,代表需要的鼓点数。

样例输入 Copy

4
1
2
5
4

样例输出 Copy

12

代码:

#include<bits/stdc++.h>
 
using namespace std;
const int N=1e6+10;
int n;
long long a[N];
 
int main(){
    while(cin>>n){
        long long num=0;
        for(int i=0;i<n;i++){
            scanf("%lld",&a[i]);
            num+=a[i];
        }
 
        cout<<num<<endl;
    }
 
    return 0;
}

D 旅行(待补题)


在这里插入图片描述
输入

单组数据。
第一行两个正整数 n,m,m 为需要处理的操作数
接下来两行,每行是一个长度为 n 的字符串,表示城市能否经过。若为 X,则表示不能经过,若为 P,则
表示可以经过。
接下来描述两行,每行 n-1 个数分别描述 w[0][i] 和 w[1][i]
接下来一行 n 个数描述 w[2][i]
接下来 m 行,每行代表需要处理的一个操作。
对于所有数据 1 ≤ n, m ≤ 200000 。

输出

对于每个询问输出一行,从询问的 x 街区到 y 街区需要经过的最短路径 (不包括起点,但包括终点),若
无法到达输出-1。

样例输入 Copy

5 5
PPPPX
PPXPP
3 7 10 9
7 9 7 9
4 9 8 1 1
1 1 10
1 1 9
1 2 3
3 3 X
1 5 5

样例输出 Copy

30
21
7
-1

代码:

在这里插入代码片

E 解密

题目描述

湖南中医药大学有含浦、东塘 2 个校区,学校办学历史悠久,前身为 1934 年的湖南国医专科学校,1953年创办湖南中医进修学校,1960 年创建普通高等本科院校——湖南中医学院,1979 年成为全国首批取得中医类研究生学历教育资格的院校,1990 年原湖南科技大学成建制并入湖南中医学院,2002 年与湖南省中医药研究院合并,2006 年经教育部批准更名为湖南中医药大学,2012 年进入湖南省一本招生序列。
目前,学校与湖南省中医药研究院实行校院合一的管理体制。学校学科门类齐全、中医药特色鲜明。学校设有 18 个学院、24 个本科专业,涵盖医、理、工、管、文等 5 大学科门类。中医诊断学在本学科研究领域居国内领先水平。
小 F 居住在含浦校区,他想和东塘校区的同学小 L 聊天,为了保证沟通安全,他发明了一种加密方式,这种加密方式是这样的:对于一个 01 串,小 F 会将其从左到右每 8 位分成一组,最后一组可能不足 8 位,对每组进行逆序操作,即如果原来是 bLbL+1bL+2 · · · bR−1bR, 逆序之后变成 bRbR−1bR−2 · · · bL−1bL。现在小 F 已经加密好了一个串,并且将其发给了小 L,你能帮助小 L 得到这串密文对应的原始信息吗?

输入

单组数据。
一行一个 01 串,代表加密后的字符串,串长度大于 0, 小于等于 100。

输出

一行字符串,代表加密后的字符串所对应的原始信。

样例输入 Copy

100010110011101

样例输出 Copy

110100011011100

代码:

#include<bits/stdc++.h>
 
using namespace std;
const int N=1e6+10;
int n;
char a[110];
 
int main(){
    while(~scanf("%s",a)){
        int len=strlen(a);
        for(int i=7;i<len;i+=8){
            for(int j=0;j<8;j++) printf("%c",a[i-j]);
        }
        int l=len%8;
        for(int j=1;j<=l;j++) printf("%c",a[len-j]);
        cout<<endl;
    }
 
    return 0;
}

F 巍巍岳麓(最小生成树)

在这里插入图片描述
输入

单组数据。
输入第一行有两个正整数 n 和 m,分别表示城市有 n 个交叉路口,m 条道路 (n <= 3000,m<=4000)。
接下来 m 行是对每条道路的描述,u,v,c 表示交叉路口 u 和 v 之间有道路相连,分值为 c(分值不会超
过 int)。最后一行两个正整数 s 和 t,表示麓山南路在交叉路口 s 和 t 相连的路上。

输出

输出两个整数 tot,max,表示你选出了几条道路,分值最大的那条的道路的分值是多少。

样例输入 Copy

4 5
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
1 4

样例输出 Copy

3 6

代码:

#include<bits/stdc++.h>

using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,m;
int b[N],f[N];
int ind,ma,mi;
struct lel{
    int l,r,w;
    bool operator< (const lel &W) const{
        return w<W.w;
    }
}a[N];

int fin(int x){
    return x==f[x]?x:fin(f[x]);
}

int main(){
    int x,y,z;
    scanf("%d %d",&n,&m);         //输入
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        a[i]={x,y,z};

    }
    scanf("%d%d",&x,&y);

    sort(a+1,a+m+1);

    for(int i=1;i<=m;i++){          //找到必加入的那条边,并记录边的序号
        if((a[i].l==x && a[i].r==y) || (a[i].l==y && a[i].r==x)){
            ind=i;
            break;
        }
    }

    mi=1e6;        //最大边的最小值
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++) f[j]=j;      //并查集的初始化

        f[x]=y;      //必须连通的路先加进去
        ma=a[ind].w;    //加入必须连通的路的值

        int k=1;           //记录加入了几条边
        for(int h=i;h<=m;h++){
            int xx=fin(a[h].l),yy=fin(a[h].r);
            if(xx!=yy){
                f[yy]=xx;
                k++;
                ma=max(ma,a[h].w);
                if(k==n-1) break;
            }
        }
        if(k==n-1) mi=min(mi,ma);     //判断是否生成最小树的
    }
    printf("%d %d\n",n-1,mi);
    return 0;
}

G Solution Sets(待补题)

题目描述

For any positive integer N, there is an integer equation:
For a given integer m, find the number of different solution sets of the integer equation when at most one Xi is allowed to be greater than m. Note that all the Xi(i ∈ [1, n]) should be positive integers

输入

There are several test files and each contains one case.
The input has one line, and there are 2 positive integers separated by space, which are respectively n, m
(n ≤ 20, m ≤ 150)

输出

The output is a single line, which is the total number of different solution sets.

样例输入 Copy

3 6

样例输出 Copy

3

提示

As for the example, there are three solution sets, that is { 2,3,6 } ,{ 3,3,3 } and { 2,4,4 }.
Equality of sets is defined as set A is said to be equal to set B if both sets have the same elements or
members of the sets, i.e. if each element of set A also belongs to each element of set B, and each element
of set B also belongs to each element of set A.

代码:

在这里插入代码片

H 百舸争流(待补题)

题目描述

橘子洲风景区位于湖南省长沙市市区对面的湘江江心,是湘江中最大的名洲,由南至北,横贯江心,西望
岳麓山,东临长沙城,四面环水,绵延数十里,狭处横约 40 米,宽处横约 140 米,形状是一个长岛,是
国家重点风景名胜区。
一天,N 名选手参加了一年一度的橘洲竞渡大赛,现在只剩下最后一场决赛了!
赛制为积分制,N 名选手的积分分别为 A1 到 AN。决赛的积分规则如下:第一名得 B1 分,第二名得 B2
分,……,第 m 名得 Bm 分,第 m+1 名至第 n 名不得分。最后第 i 名选手的总得分为 Ai 加上他在决
赛中的得分。
我们按总分为第一关键字、名字的字典序为第二关键字对选手进行排序。现告诉你一名选手的名字,希望
你告诉他,他最终的排名最前可能是多少,最后可能是多少。

输入

单组数据。
第一行为一个数 n,表示有 n 名选手 (1 ≤ n ≤ 105)。
接下来有 n 行,每行由一个字符串 S 和一个非负整数 Ai 表示,代表该人的名字和决赛之前的总分。
(名字仅由英文字母和数字表示,长度不超过 20,没有相同名字的两个人,0 ≤ Ai ≤ 106)。
接下来一个数 m(0 ≤ m ≤ n)。
接下来一行 m 个数字依次表示 B1, B2, B3, · · · , Bm (0 ≤ Bi ≤ 106)。
最后一个字符串表示询问的选手的名字。

输出

输出两个数,第一个表示最终排名最前可能多少,第二个表示最后可能多少。

样例输入 Copy

3
CH1 10
CH2 20
CH3 40
2
20 10
CH1

样例输出 Copy

2 3

代码:

在这里插入代码片

I 最长不下降子序列(待补题)

题目描述
给定一个序列 a,求去除 a 中一段连续长度为 L 的序列后,a 的最长不下降子序列的长度的最大值。

输入

单组数据。
第一行两个整数 n,L 表示序列的长度为 n,L 如题意所示。
第二行 n 个数表示序列 a
n ≤ 105, 0 ≤ L ≤ n

输出

输出一个整数表示最长不下降子序列长度的最大值

样例输入 Copy

6 3
2 1 3 6 4 5

样例输出 Copy

3

代码:

在这里插入代码片

J Mode

题目描述

Given N(1 ≤ N ≤ 10000) unordered positive integers ranging from 1 to 30000. The same positive
integer may appear multiple times and the most frequently occurring integer is called the mode. Find
the sequence’s mode(s) and the number of times it appears.

输入

There are several test files and each contains one case.
The first line of the input is a positive integers N and the second line begins with N positive integers.

输出

The output has several lines, two for each line. The first is the mode, and the second is the number of
times the mode appears. 1 space between the middle. If there are multiple modes, print the modes in
ascending order.

样例输入 Copy

12
2 4 2 3 2 5 3 7 2 3 4 3

样例输出 Copy

2 4
3 4

代码:

#include<bits/stdc++.h>
 
using namespace std;
const int N=3e4+10;
int n;
int a[N];
 
int main(){
    int ma=0;
    while(~scanf("%d",&n)){
        ma=0;
        memset(a,0,sizeof a);
        for(int i=0;i<n;i++){
            int x;
            cin>>x;
            a[x]++;
            if(ma<x) ma=x;
        }
 
        int m=0,b=0;
        for(int i=0;i<=ma;i++){
            if(a[i]>m){
                m=a[i];
                b=i;
            }
        }
        for(int i=b;i<=ma;i++){
            if(a[i]==m){
                cout<<i<<" "<<m<<endl;
            }
        }
    }
 
    return 0;
}

K Matrix

题目描述

There is a N×N matrix. Dr.L want to choose N grid from the matrix and number them with different
number from 1 to N. At the same time, he doesn’t like the grid numbered with i locate in the i-th row
or the i-th column. And any two selected grids cannot be in the same row or in the same column. How
many schemes can Dr.L find? Please output the answer modulo M.

输入

There are several test files and each contains one case.
Two positive initegers N and M (N ≤ 1015, M ≤ 106)

输出

The number of schemes modulo M.

样例输入 Copy

2 1000

样例输出 Copy

1

这是一个找规律的题,因为数据范围有10^15,这个问了大佬补的题,大佬说找规律,求n就要考虑n和n-1的关系。为了找规律我把答案分的太细了结果啥规律都看不出来了。。。

1 ____ 0 = 12
2 ____ 1 = 22
3 ____ 4 = 92
4 ____ 81 = 442
5 ____ 1936 = 2652
6 ____ 70225 = …
7 ____ 3437316 = …
8 ____ 220017889 = …

代码:

#include<bits/stdc++.h>

using namespace std;
const int N=1e6+10;
typedef long long ll;
long long n,m;
long long a[N];

int main(){
    a[1]=0;
    a[2]=1;
    int k=3;
    while(cin>>n>>m){
        n%=m;
        for(int i=k;i<=n;i++){
            a[i]=(i-1)*(a[i-1]+a[i-2])%m;
            k++;
        }

        cout<<a[n]*a[n]%m<<endl;
    }
    return 0;
}

L 药剂

题目描述

小 Q 是一名出色的药剂师,为了合成新的药剂,他将药材放入了一个 n×m 的网格状药材盒(下标从 1开始),用 n 个长度为 m 的字符串 (仅由小写字母组成) 代表这个药材盒,一共有 26 种药材,每个字母代表一种药材。
为了达到最优的疗效,小 Q 需要尝试不同的配比方案,为此他进行了 q 次操作,操作有两种:
操作 0:0 x y z ,将下标为 (x,y) 处的药材改为 z 药材
操作 1:1 x1 y1 x2 y2 ,询问矩形 (x1 ≤ x ≤ x2, y1 ≤ y ≤ y2) 区域内不同的药材各出现了多少次

输入

多组数据。
每组数据第一行两个整数 n,m(1 ≤ n, m ≤ 1000)。
接下来 n 行,每行一个长度为 m 的字符串。
接下来一个整数 q (q ≤ 20000),下面 q 行代表要处理的操作,格式如题意所示。

输出

对于每个操作 1 输出一行,每行 26 个整数,表示 a-z 药材出现的次数,用一个空格分割,行末不允许有
多余空格。

样例输入 Copy

3 3
aaa
bbb
ccc
3
1 2 1 2 2
0 2 2 z
1 1 1 2 3
5 4
abcd
bcda
cdab
dabc
abcd
4
0 4 1 x
1 1 2 2 4
0 2 1 l
1 1 1 3 3

样例输出 Copy

0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0
3 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1
1 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0
2 1 3 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0

代码:

#include<bits/stdc++.h>
 
using namespace std;
int n,m;
int a[30];
char c[1010][1010];
 
int main(){
    while(cin>>n>>m){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++) cin>>c[i][j];
 
        }
 
        int q;
        cin>>q;
        while(q--){
            int x,y;
            char z;
            cin>>x;
            if(x==0){
                cin>>x>>y;
                cin>>z;
                c[x][y]=z;
            }
            else if(x==1){
                int x1,x2,y1,y2;
                cin>>x1>>y1>>x2>>y2;
 
                memset(a,0,sizeof a);
                for(int i=x1;i<=x2;i++){
                    for(int j=y1;j<=y2;j++){
                        a[c[i][j]-'a']++;
                    }
                }
 
                for(int i=0;i<26;i++){
                    if(i!=0) cout<<" ";
                    cout<<a[i];
                }
                cout<<endl;
            }
 
 
        }
    }
 
    return 0;
}
 我感觉我的代码还是有些复杂,大家如果有更加简洁的代码,欢迎一起来交流^ _ ^
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值