算法训练与程序竞赛题目集合(L4)

目录

L4-103 就不告诉你

输入格式:

输出格式:

输入样例:

输出样例:

L4-104 Wifi密码

输入格式:

输出格式:

输入样例:

输出样例:

L4-105 冠军魔术

输入格式:

输出格式:

输入样例 1:

输出样例 1:

输入样例 2:

输出样例 2:

L4-106 判断题

输入格式:

输出格式:

输入样例:

输出样例:

L4-107 检查密码

输入格式:

输出格式:

输入样例:

输出样例:

L4-108 谷歌的招聘

输入格式:

输出格式:

输入样例 1:

输出样例 1:

输入样例 2:

输出样例 2:

L4-109 考试周

输入格式:

输出格式:

输入样例:

输出样例:

L4-110 真的恭喜你

输入格式:

输出格式:

输入样例 1:

输出样例 1:

输入样例 2:

输出样例 2:

L4-111 Cassels方程

输入格式:

输出格式:

输入样例:

输出样例:

L4-112 不变初心数

输入格式:

输出格式:

输入样例:

输出样例:

L4-113 编程团体赛

输入格式:

输出格式:

输入样例:

输出样例:

L4-114 自动编程

输入格式:

输出格式:

输入样例:

输出样例:

L4-115 太神奇了

输入格式:

输出格式:

输入样例:

输出样例:

样例说明

L4-116 字母串

输入格式:

输出格式:

输入样例:

输出样例:

L4-117 矩阵列平移

输入格式:

输出格式:

输入样例:

输出样例:

L4-118 均是素数

输入格式:

输出格式:

输入样例:

输出样例:

L4-201 出栈序列的合法性

输入格式:

输出格式:

输入样例:

输出样例:

 

L4-202 二叉搜索树的2层结点统计

L4-203 三足鼎立

输入格式:

输出格式:

输入样例:

输出样例:

样例解释:

L4-204 盲盒包装流水线

输入格式:

输出格式:

输入样例:

输出样例:

L4-205 浪漫侧影

输入格式:

输出格式:

输入样例:

输出样例:

L4-301 狼人杀

输入格式:

输出格式:

输入样例 1:

输出样例 1:

输入样例 2:

输出样例 2(解不唯一):

输入样例 3:

输出样例 3:

L4-302 拼题A打卡奖励

输入格式:

输出格式:

输入样例:

输出样例:

样例解释:


L4部分的题目难度可以说是比较混乱,又简单的也有难的,比较考验实际问题的求解。

到这里算法程序设计竞赛的188道题就全部结束了,希望大家不管是在期末考试复习还是平时的练习都取得满满的收获。

L4-103 就不告诉你

分数 7

全屏浏览

切换布局

作者 CHEN, Yue

单位 浙江大学

做作业的时候,邻座的小盆友问你:“五乘以七等于多少?”你应该不失礼貌地围笑着告诉他:“五十三。”本题就要求你,对任何一对给定的正整数,倒着输出它们的乘积。

53.jpg

输入格式:

输入在第一行给出两个不超过 1000 的正整数 A 和 B,其间以空格分隔。

输出格式:

在一行中倒着输出 A 和 B 的乘积。

输入样例:

5 7

输出样例:

53
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int a=sc.nextInt();
        int b=sc.nextInt();
        String s=String.valueOf(a*b);
        int flag=0;
        for(int i=0;i<s.length();i++){
            if(s.charAt(s.length()-i-1)=='0'&&i==0){
                flag=1;
                continue;
            }
            if(i!=0&&s.charAt(s.length()-i-1)!='0')
                flag=0;
            if(flag==0)
            System.out.print(s.charAt(s.length()-i-1));
        }
    }
}

 

L4-104 Wifi密码

分数 5

全屏浏览

切换布局

作者 CHEN, Yue

单位 浙江大学

下面是微博上流传的一张照片:“各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1;B-2;C-3;D-4;请同学们自己作答,每两日一换。谢谢合作!!~”—— 老师们为了促进学生学习也是拼了…… 本题就要求你写程序把一系列题目的答案按照卷子上给出的对应关系翻译成 wifi 的密码。这里简单假设每道选择题都有 4 个选项,有且只有 1 个正确答案。

wifi.jpg

输入格式:

输入第一行给出一个正整数 N(≤ 100),随后 N 行,每行按照 编号-答案 的格式给出一道题的 4 个选项,T 表示正确选项,F 表示错误选项。选项间用空格分隔。

输出格式:

在一行中输出 wifi 密码。

输入样例:

8
A-T B-F C-F D-F
C-T B-F A-F D-F
A-F D-F C-F B-T
B-T A-F C-F D-F
B-F D-T A-F C-F
A-T C-F B-F D-F
D-T B-F C-F A-F
C-T A-F B-F D-F

输出样例:

13224143
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        sc.nextLine();
        String mima="";
        for(int i=0;i<n;i++){
            String s=sc.nextLine();
            int index=s.indexOf("T");
            if(s.charAt(index-2)=='A')
                mima=mima+'1';
             if(s.charAt(index-2)=='B')
                mima=mima+'2';
             if(s.charAt(index-2)=='C')
                mima=mima+'3';
             if(s.charAt(index-2)=='D')
                mima=mima+'4';
        }
        System.out.println(mima);
    }
}

 

L4-105 冠军魔术

分数 5

全屏浏览

切换布局

作者 陈越

单位 浙江大学

魔术.jpg

2018年FISM(世界魔术大会)近景总冠军简纶廷的表演中有一个情节:以桌面上一根带子为界,当他将纸牌从带子的一边推到另一边时,纸牌会变成硬币;把硬币推回另一边会变成纸牌。

这里我们假设纸牌会变成等量的硬币,而硬币变成纸牌时,纸牌的数量会加倍。那么给定纸牌的初始数量,当他来回推了 N 次(来/回各算一次)后,手里拿的是纸牌还是硬币?数量是多少?

输入格式:

输入在一行里给出两个正整数,分别是纸牌的初始数量和魔术师推送的次数。这里假设初始状态下魔术师手里全是纸牌。

输出格式:

如果最后魔术师手里是纸牌,输出 0 和纸牌数量;如果是硬币,则输出 1 和硬币数量。数字间须有 1 个空格。题目保证结果数值不超出整型范围(即 231−1)。

输入样例 1:

3 7

输出样例 1:

1 24

输入样例 2:

8 4

输出样例 2:

0 32
#include<stdio.h>
int main(){
	int chushi,c,a,j,i;
	scanf("%d %d",&chushi,&c);
	if(c%2==0){
		a=0;
	}
	else{
		a=1;
	}
	j=chushi;
	if(a==0){
		for(i=1;i<=c/2;i++){
			j=j*2;
		}
	}
	if(a==1){
		for(i=1;i<=(c-1)/2;i++){
			j=j*2;
	}
}
	printf("%d %d",a,j);
	return 0;
}

 

L4-106 判断题

分数 5

全屏浏览

切换布局

作者 CHEN, Yue

单位 浙江大学

判断题的评判很简单,本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分。

输入格式:

输入在第一行给出两个不超过 100 的正整数 N 和 M,分别是学生人数和判断题数量。第二行给出 M 个不超过 5 的正整数,是每道题的满分值。第三行给出每道题对应的正确答案,0 代表“非”,1 代表“是”。随后 N 行,每行给出一个学生的解答。数字间均以空格分隔。

输出格式:

按照输入的顺序输出每个学生的得分,每个分数占一行。

输入样例:

3 6
2 1 3 3 4 5
0 0 1 0 1 1
0 1 1 0 0 1
1 0 1 0 1 0
1 1 0 0 1 1

输出样例:

13
11
12
#include<iostream>
using namespace std;
struct ti{
    int fenzhi;
    int duicuo;
};
int main(){
    int n,m;
    cin>>n>>m;
    struct ti ti[m];
    for(int i=0;i<m;i++){
        cin>>ti[i].fenzhi;
    }
    for(int i=0;i<m;i++){
        cin>>ti[i].duicuo;
    }
    for(int i=0;i<n;i++){
        int sum=0;
        for(int j=0;j<m;j++){
            int t;
            cin>>t;
            if(t==ti[j].duicuo)
                sum=sum+ti[j].fenzhi;
        }
        cout<<sum<<endl;
    }
}

 

L4-107 检查密码

分数 5

全屏浏览

切换布局

作者 陈越

单位 浙江大学

本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能。该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母、数字和小数点 .,还必须既有字母也有数字。

输入格式:

输入第一行给出一个正整数 N(≤ 100),随后 N 行,每行给出一个用户设置的密码,为不超过 80 个字符的非空字符串,以回车结束。

注意: 题目保证不存在只有小数点的输入。

输出格式:

对每个用户的密码,在一行中输出系统反馈信息,分以下5种:

  • 如果密码合法,输出Your password is wan mei.
  • 如果密码太短,不论合法与否,都输出Your password is tai duan le.
  • 如果密码长度合法,但存在不合法字符,则输出Your password is tai luan le.
  • 如果密码长度合法,但只有字母没有数字,则输出Your password needs shu zi.
  • 如果密码长度合法,但只有数字没有字母,则输出Your password needs zi mu.

输入样例:

5
123s
zheshi.wodepw
1234.5678
WanMei23333
pass*word.6

输出样例:

Your password is tai duan le.
Your password needs shu zi.
Your password needs zi mu.
Your password is wan mei.
Your password is tai luan le.
#include<iostream>
using namespace std;
int main(){
    int n;
    cin>>n;
    getchar();
    for(int i=0;i<n;i++){
        string str;
        getline(cin,str);
        if(str.length()<6)
            cout<<"Your password is tai duan le."<<endl;
        else{
            int havenum = 0;//数字
            int havech = 0;//字母
            int haveother = 0;//其他字符
            for(int j=0;j<str.length();j++){
                if(str[j]>='0'&&str[j]<='9')
                    havenum=1;
                else if((str[j]>='a'&&str[j]<='z')||(str[j]>='A'&&str[j]<='Z'))
                    havech=1;
                else if(str[j]!='.')
                    haveother=1;
            }

            if(haveother==1)
                cout<<"Your password is tai luan le."<<endl;
            else if(havech==1&&havenum==1)
                cout<<"Your password is wan mei."<<endl;
            else if(havech==0)
                cout<<"Your password needs zi mu."<<endl;
            else
                cout<<"Your password needs shu zi."<<endl;
        }
    }
    return 0;
}

 

L4-108 谷歌的招聘

分数 20

全屏浏览

切换布局

作者 陈越

单位 浙江大学

2004 年 7 月,谷歌在硅谷的 101 号公路边竖立了一块巨大的广告牌(如下图)用于招聘。内容超级简单,就是一个以 .com 结尾的网址,而前面的网址是一个 10 位素数,这个素数是自然常数 e 中最早出现的 10 位连续数字。能找出这个素数的人,就可以通过访问谷歌的这个网站进入招聘流程的下一步。

prime.jpg

自然常数 e 是一个著名的超越数,前面若干位写出来是这样的:e = 2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059921... 其中粗体标出的 10 位数就是答案。

本题要求你编程解决一个更通用的问题:从任一给定的长度为 L 的数字中,找出最早出现的 K 位连续数字所组成的素数。

输入格式:

输入在第一行给出 2 个正整数,分别是 L(不超过 1000 的正整数,为数字长度)和 K(小于 10 的正整数)。接下来一行给出一个长度为 L 的正整数 N。

输出格式:

在一行中输出 N 中最早出现的 K 位连续数字所组成的素数。如果这样的素数不存在,则输出 404。注意,原始数字中的前导零也计算在位数之内。例如在 200236 中找 4 位素数,0023 算是解;但第一位 2 不能被当成 0002 输出,因为在原始数字中不存在这个 2 的前导零。

输入样例 1:

20 5
23654987725541023819

输出样例 1:

49877

输入样例 2:

10 3
2468001680

输出样例 2:

404
#include <iostream>
#include <cmath>
using namespace std;
bool isPrime(int num){
    if (num == 0 || num == 1)
        return false;
    int m = sqrt(num);
    for (int i = 2; i <= m; ++i) {
        if (num % i == 0)
            return false;
    }
    return true;
}
int main(){
    int L, K;
    string str1,str2;
    cin>>L>>K;
    cin>>str1;
    int i;
    int num;
    for(i = 0; i <= L - K; ++i){
        str2 = str1.substr(i, K);
        num = stoi(str2);
        if (isPrime(num)){
            cout << str2;
            break;
        }
}
    if(i>L-K)
        cout << "404";
}

 

L4-109 考试周

分数 4

全屏浏览

切换布局

作者 陈越

单位 浙江大学

ksz.jpg

考试周快到了,浙江大学的电子屏又调皮了…… 本题请你帮小编写一个自动倒计时的程序,对给定的日期(例如“腊八”就对应 8)和倒计时天数(例如电子屏上的“四天之后”就对应 4),自动调整公式里的分母(例如 8/2=4 里面的那个 2)。

输入格式:

输入在一行中给出两个正整数:A 是给定的日期,不超过 30;B 是倒计时天数,不超过 10。

输出格式:

在一行中输出公式 A/X=B,其中 X 是满足等式的数字,输出时保留小数点后 1 位即可。

输入样例:

8 3

输出样例:

8/2.7=3
#include<iostream>
using namespace std;
int main(){
    double a,b;
    cin>>a>>b;
    double c=a/b;
    printf("%.0lf",a);
    cout<<"/";
    printf("%.1lf",c);
    cout<<"="<<b;
}

 

L4-110 真的恭喜你

分数 5

全屏浏览

切换布局

作者 陈越

单位 浙江大学

当别人告诉你自己考了 x 分的时候,你要回答说:“恭喜你考了 x 分!”比如小明告诉你他考了90分,你就用汉语拼音打出来 gong xi ni kao le 90 fen!

但是如果小明没考好,比如只考了 20 分,你也“恭喜”人家就不对了。这时候你应该安慰他说:“考了 20 分别泄气!”用汉语拼音写出来就是 kao le 20 fen bie xie qi!

输入格式:

输入在一行里给出一位小朋友的分数。这个分数是一个 0 到 100 之间的整数。

输出格式:

在一行中输出你对这位小朋友说的话。如果人家考到不低于 90 分,就说 gong xi ni kao le X fen!;如果不到 90 分,就说 kao le X fen bie xie qi!。其中 X 是小朋友输入的分数。

输入样例 1:

95

输出样例 1:

gong xi ni kao le 95 fen!

输入样例 2:

89

输出样例 2:

kao le 89 fen bie xie qi!
#include<iostream>
using namespace std;
int main(){
    int fen;
    cin>>fen;
    if(fen>=90)
        cout<<"gong xi ni kao le "<<fen<<" fen!";
    else
        cout<<"kao le "<<fen<<" fen bie xie qi!";
}

 

L4-111 Cassels方程

分数 4

全屏浏览

切换布局

作者 陈越

单位 浙江大学

Cassels方程是一个在数论界产生了巨大影响的不定方程:x2+y2+z2=3xyz。该方程有无穷多自然数解。

本题并不是要你求解这个方程,只是判断给定的一组 (x,y,z) 是不是这个方程的解。

输入格式:

输入在第一行给出一个不超过 10 的正整数 N,随后 N 行,每行给出 3 个正整数 0<x≤y≤z≤1000。

输出格式:

对于每一组输入,如果是一组解,就在一行中输出 Yes,否则输出 No

输入样例:

2
1 1 1
5 6 7

输出样例:

Yes
No
#include<iostream>
using namespace std;
int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        int x,y,z;
        cin>>x>>y>>z;
        if(x*x+y*y+z*z==3*x*y*z)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
}

 

L4-112 不变初心数

分数 5

全屏浏览

切换布局

作者 陈越

单位 浙江大学

不变初心数是指这样一种特别的数,它分别乘 2、3、4、5、6、7、8、9 时,所得乘积各位数之和却不变。例如 18 就是这样的数:18 的 2 倍是 36,3+6=9;18 的 3 倍是 54,5+4=9;…… 18 的 9 倍是 162,1+6+2=9。对于 18 而言,9 就是它的初心。本题要求你判断任一个给定的数是否有不变的初心。

输入格式:

输入在第一行中给出一个正整数 N(≤ 100)。随后 N 行,每行给出一个不超过 105 的正整数。

输出格式:

对每个给定的数字,如果它有不变的初心,就在一行中输出它的初心;否则输出 NO

输入样例:

4
18
256
99792
88672

输出样例:

9
NO
36
NO
#include<iostream>
using namespace std;
int panduan(int x){
    int sum=0;
    while(x>0){
        sum+=x%10;
        x=x/10;
    }
    return sum;
}
int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        int t;
        cin>>t;
        int flag=0;
        for(int j=2;j<=9;j++){
            if(panduan(t)!=panduan(t*j)){
                flag=1;
                break;
            }
        }
        if(flag==1)
            cout<<"NO"<<endl;
        else
            cout<<panduan(t)<<endl;
    }
}

 

L4-113 编程团体赛

分数 20

全屏浏览

切换布局

作者 CHEN, Yue

单位 浙江大学

编程团体赛的规则为:每个参赛队由若干队员组成;所有队员独立比赛;参赛队的成绩为所有队员的成绩和;成绩最高的队获胜。

现给定所有队员的比赛成绩,请你编写程序找出冠军队。

输入格式:

输入第一行给出一个正整数 N(≤104),即所有参赛队员总数。随后 N 行,每行给出一位队员的成绩,格式为:队伍编号-队员编号 成绩,其中队伍编号为 1 到 1000 的正整数,队员编号为 1 到 10 的正整数,成绩为 0 到 100 的整数。

输出格式:

在一行中输出冠军队的编号和总成绩,其间以一个空格分隔。注意:题目保证冠军队是唯一的。

输入样例:

6
3-10 99
11-5 87
102-1 0
102-3 100
11-9 89
3-2 61

输出样例:

11 176
#include<iostream>
using namespace std;
int main(){
    int n,res=0,ans;
    cin>>n;
    int q[1001]={0};
    while(n--){
        int x,y,sc;
        char c;
        cin>>x>>c>>y>>sc;
        q[x]+=sc;
    }
    for(int i=1;i<1001;i++)
        if(q[i]!=0&&res<q[i]) res=q[i],ans=i;
    cout<<ans<<" "<<res;
}

 

L4-114 自动编程

分数 4

全屏浏览

切换布局

作者 陈越

单位 浙江大学

输出语句是每个程序员首先要掌握的语句。Python 的输出语句很简单,只要写一个 print(X) 即可,其中 X 是需要输出的内容。

本题就请你写一个自动编程机,对任何一个要输出的整数 N,给出输出这个整数的 Python 语句。

输入格式:

输入给出一个不超过 105 的正整数。

输出格式:

在一行中打印输出这个整数的 Python 语句,其中不包含任何空格。

输入样例:

520

输出样例:

print(520)
n=input()
print("print("+n+")")

 

L4-115 太神奇了

分数 4

全屏浏览

切换布局

作者 陈越

单位 浙江大学

sq.jpg

“告诉大家一个神奇的消息,太神奇了:明年全世界所有的人都同岁,全部都等于2022。明年的日子很特别,大概每1000年才会有一次。明年你的周岁年龄+你的出生年,每个人都是2022年。例如:你明年57加上1965年生的,加起来就是2022年。特别奇怪,连中外专家都无法解释!你计算一下,看看是不是2022。真是千年等一回呀!真准!转朋友圈,让大伙都算一下吧!”

据说这个“电子包浆”贴每年都会出现。本题就请你根据发贴人提到的周岁年龄和出生年,判断其发贴的时候是哪一年。

输入格式:

输入在第一行中给出两个正整数,即周岁年龄和出生年,其中年龄在 (0, 200) 区间内,出生年在 (1900, 2022) 区间内。

输出格式:

在一行中输出发贴年份。

输入样例:

57 1965

输出样例:

2021

样例说明

因为贴子里说“明年全世界所有的人都同岁”,所以发贴是在今年,即 2021 年。

#include<iostream>
using namespace std;
int main(){
    int x,y;
    cin>>x>>y;
    cout<<x+y-1<<endl;
}

 

L4-116 字母串

分数 7

全屏浏览

切换布局

作者 陈越

单位 浙江大学

英语老师要求学生按照如下规则写一串字母:

  • 如果写了某个大写字母,下一个就必须写同个字母的小写,或者写字母表中下一个字母的大写;
  • 如果写了某个小写字母,下一个就必须写同个字母的大写,或者写字母表中前一个字母的小写;
  • 当然也可以什么都不写,就结束这个字母串。

例如 aAaABCDdcbBC 就是一个合法的字母串;而 dEFfeFGhI 就是非法的。注意 a 没有前一个字母, Z 也没有下一个字母。

现在面对全班学生交上来的作业,老师请你写个程序自动批改。

输入格式:

输入在第一行给出一个不超过 100 的正整数 N。随后 N 行,每行给出一位学生的作业,即仅由英文字母组成的非空字母串,长度不超过 2×106。

输出格式:

对每位学生的作业,如果正确就在一行中输出 Y,否则输出 N

输入样例:

2
aAaABCDdcbBC
dEFfeFGhI

输出样例:

Y
N
#include<iostream>
using namespace std;
int main(){
    int n,i,x;
    string s;
    cin>>n;
    while(n--){
        cin>>s;
        x=0;
        for(i=0;i<s.size()-1;i++){
            if(s[i]>='A'&&s[i]<='Z'&&(s[i+1]==s[i]+32||(s[i+1]==s[i]+1&&s[i]!='Z')))continue;
            else if(s[i]>='a'&&s[i]<='z'&&(s[i+1]==s[i]-32||(s[i+1]==s[i]-1&&s[i]!='a')))continue;
            else{
                x=1;
                break;
            }
        }
        if(x==1)
            cout<<"N\n";
        else
            cout<<"Y\n";
    }
}

 

L4-117 矩阵列平移

分数 20

全屏浏览

切换布局

作者 陈越

单位 浙江大学

给定一个 n×n 的整数矩阵。对任一给定的正整数 k<n,我们将矩阵的偶数列的元素整体向下依次平移 1、……、k、1、……、k、…… 个位置,平移空出的位置用整数 x 补。你需要计算出结果矩阵的每一行元素的和。

输入格式:

输入第一行给出 3 个正整数:n(<100)、k(<n)、x(<100),分别如题面所述。

接下来 n 行,每行给出 n 个不超过 100 的正整数,为矩阵元素的值。数字间以空格分隔。

输出格式:

在一行中输出平移后第 1 到 n 行元素的和。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

7 2 99
11 87 23 67 20 75 89
37 94 27 91 63 50 11
44 38 50 26 40 26 24
73 85 63 28 62 18 68
15 83 27 97 88 25 43
23 78 98 20 30 81 99
77 36 48 59 25 34 22

输出样例:

440 399 369 421 302 386 428

样例解读

需要平移的是第 2、4、6 列。给定 k=2,应该将这三列顺次整体向下平移 1、2、1 位(如果有更多列,就应该按照 1、2、1、2 …… 这个规律顺次向下平移),顶端的空位用 99 来填充。平移后的矩阵变成:

11 99 23 99 20 99 89
37 87 27 99 63 75 11
44 94 50 67 40 50 24
73 38 63 91 62 26 68
15 85 27 26 88 18 43
23 83 98 28 30 25 99
77 78 48 97 25 81 22
#include<bits/stdc++.h>
using namespace std;
int n,m,p,k;
int main(){
	int i,j;
	cin>>n>>k>>p;
    int a[n+1][n+1];
    int z[n+1];
	for(i=1; i<=n; i++){
		for(j=1; j<=n; j++){
			cin>>a[i][j];
		}
	}
	int cnt=1;
	for(j=1; j*2<=n; j++){
		z[j*2]=cnt++;
		if(cnt==k+1)
		cnt=1;
	}
	for(i=1; i<=n; i++){
		int sum=0;
		for(j=1; j<=n; j++){
			if(j%2){
				sum+=a[i][j];
				continue;
			}
			if(i<=z[j]){
				sum+=p;
			}
			else
			sum+=a[i-z[j]][j];
		}
		if(i==1)
		printf("%d",sum);
		else
		printf(" %d",sum);
	}

}

 

L4-118 均是素数

分数 20

全屏浏览

切换布局

作者 陈越

单位 浙江大学

在给定的区间 [m,n] 内,是否存在素数 p、q、r(p<q<r),使得 pq+r、qr+p、rp+q 均是素数?

输入格式:

输入给出区间的两个端点 0<m<n≤1000,其间以空格分隔。

输出格式:

在一行中输出满足条件的素数三元组的个数。

输入样例:

1 35

输出样例:

10

样例解读

满足条件的 10 组解为:

2, 3, 5
2, 3, 7
2, 3, 13
2, 3, 17
2, 5, 7
2, 5, 13
2, 5, 19
2, 5, 31
2, 7, 23
2, 13, 17
#include<iostream>
#include<cmath>
using namespace std;
int panduan(int x){
    if(x==1)
        return 0;
    for(int i=2;i<=sqrt(x);i++){
        if(x%i==0)
            return 0;
    }
    return 1;//意思是是素数
}
int main(){
    int m,n;
    cin>>m>>n;
    int sum=0;
    for(int i=m;i<=n-2;i++){
        if(panduan(i)==1){
            for(int j=i+1;j<=n-1;j++){
                if(panduan(j)==1){
                    for(int k=j+1;k<=n;k++){
                         if(panduan(k)==1){
                             if(panduan(i*j+k)==1&&panduan(i*k+j)==1&&panduan(j*k+i)==1)
                                 sum++;
                         }
                  }
            }
          }
        }
    }
    cout<<sum;
}

 

L4-201 出栈序列的合法性

分数 35

全屏浏览

切换布局

作者 陈越

单位 浙江大学

给定一个最大容量为 m 的堆栈,将 n 个数字按 1, 2, 3, ..., n 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 m=5、n=7,则我们有可能得到{ 1, 2, 3, 4, 5, 6, 7 },但不可能得到{ 3, 2, 1, 7, 5, 6, 4 }。

输入格式:

输入第一行给出 3 个不超过 1000 的正整数:m(堆栈最大容量)、n(入栈元素个数)、k(待检查的出栈序列个数)。最后 k 行,每行给出 n 个数字的出栈序列。所有同行数字以空格间隔。

输出格式:

对每一行出栈序列,如果其的确是有可能得到的合法序列,就在一行中输出YES,否则输出NO

输入样例:

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

输出样例:

YES
NO
NO
YES
NO
#include <iostream>
#include<stack>
using namespace std;
int v[1001]; // 存放待检序列
int main(){
    int m, n, k;
    cin>>m>>n>>k;
    for (int i=0;i<k;i++){
        for (int j=0;j<n;j++)
            cin>>v[j];
        stack<int> M;
        int flag=1,now=1;
        M.push(0); //垫上一个数字为了防止暴毙,因为如果没数字就无法调用栈顶
        //也可以提前将v[0]进栈,不想改了就这样吧
        for(int j=0;j<n;j++){
            while(j<n&&v[j]==M.top()){//如果顺序一致就一直出
                M.pop();
                j++;
            }
            if(M.top()>v[j]){//如果说发现栈顶比当前数字大,那绝对不可能
                flag=0;
                break;
            }
            if (M.top()<v[j]){  //如果说栈顶比当前要小,那么要把其他的入栈
                while (now<=v[j]){
                    M.push(now);
                    now++;
                    if (M.size()>m+1){//栈满了
                        flag=0;
                        break;
                    }
                }
                M.pop();
            }
            if(flag==0)//栈满就出
                break;
        }
        if (flag==1)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
}

 

L4-202 二叉搜索树的2层结点统计

分数 35

全屏浏览

切换布局

作者 陈越

单位 浙江大学

二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。

将一系列数字按给定顺序插入一棵初始为空的二叉搜索树,你的任务是统计结果树中最下面 2 层的结点数。

输入格式:输入在第一行给出一个正整数 N (≤1000),为插入数字的个数。第二行给出 N 个 [−1000,1000] 区间内的整数。数字间以空格分隔。

输出格式:在一行中输出最下面 2 层的结点总数。

输入样例:9
25 30 42 16 20 20 35 -5 28
输出样例:6

//首先我们先确定下思路
//由于最终想要最下面两层的节点总数,先想到直接建树然后层序遍历
#include<iostream>
#include<queue>
using namespace std;
int n;
struct tree {
    int key;
    tree *left;
    tree *right;
};
int vt[1001];
int Max; //记录每层节点数、最深层
queue<struct tree*> q; //通过队列遍历每一层的结点
void dfs(tree *root,int depth){
    if(root==NULL)
        return;
    Max=max(Max, depth);
    q.push(root);
    vt[depth]++;
    while(q.empty()==false){//不为空
        tree *temp = q.front();
        q.pop();
        if(temp->left)
            dfs(temp->left,depth+1);
        if(temp->right)
            dfs(temp->right,depth+1);
    }
}
tree* insert(tree *root,int key) {
    if(root==NULL){
        root=new(tree);
        root->key=key;
        root->left=NULL;
        root->right=NULL;
    }
    else{
        if(root->key<key){
            root->right=insert(root->right,key);
        }
        else
            root->left=insert(root->left,key);
    }
    return root;
}
int main(){
    cin>>n;
    int key;
    tree *root=NULL;
    for (int i=0;i<n;i++){ 
        cin>>key;
        root = insert(root, key); //建树
    }
    dfs(root,1);
    cout<<vt[Max]+vt[Max-1];
}

 

L4-203 三足鼎立

分数 35

全屏浏览

切换布局

作者 陈越

单位 浙江大学

当三个国家中的任何两国实力之和都大于第三国的时候,这三个国家互相结盟就呈“三足鼎立”之势,这种状态是最稳定的。

现已知本国的实力值,又给出 n 个其他国家的实力值。我们需要从这 n 个国家中找 2 个结盟,以成三足鼎立。有多少种选择呢?

输入格式:

输入首先在第一行给出 2 个正整数 n(2≤n≤105)和 P(≤109),分别为其他国家的个数、以及本国的实力值。随后一行给出 n 个正整数,表示n 个其他国家的实力值。每个数值不超过 109,数字间以空格分隔。

输出格式:

在一行中输出本国结盟选择的个数。

输入样例:

7 30
42 16 2 51 92 27 35

输出样例:

9

样例解释:

能联合的另外 2 个国家的 9 种选择分别为:

{16, 27}, {16, 35}, {16, 42}, {27, 35}, {27, 42}, {27, 51}, {35, 42}, {35, 51}, {42, 51}。

//在这道题没啥好说的,暴力看看过不过得了
//很显然啊,暴力没办法
//我们可以先排序,直接二分
//好抽象啊为什么要用longlong
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
    long long n,P;
    cin>>n>>P;
    long long a[n];
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sort(a,a+n);
    long long num=0;
     for(int i=0;i<n;i++) {
        int l=upper_bound(a+i+1,a+n,fabs(P-a[i]))-a;
        int r=lower_bound(a+i+1,a+n,P+a[i])-a;
        num+=(r-l);
    }
    cout<<num<<endl;
}

 

L4-204 盲盒包装流水线

分数 35

全屏浏览

切换布局

作者 陈越

单位 浙江大学

众所周知,PAT 有 9 枚徽章,分别对应青铜、白银、黄金、白金、钻石、大师、王者、大圣、天神这 9 个段位,只有成绩非常优秀的考生才有资格获得刻有自己名字的徽章。现在,PAT 制作了徽章的小型纪念版,要制成盲盒给大家玩了!

下图是一条盲盒包装流水线的示意图。首先徽章通过进货口被压入货栈里,空盒在履带上从左向右传送。每次从货栈里弹出一枚徽章,进入打包机,装入一只空盒,打包后继续向右边传送。当货栈为空时,打包机会暂停,等待下一批徽章压入货栈。

lsx.png

每只盒子都有一个编号,小拼姐姐手里有进入流水线的空盒编号顺序表,也有每一批送往货栈的徽章顺序表,这样她其实可以知道每只盒子里装了哪种徽章。有些小朋友收到了盲盒,就想在拆封前问无所不知的小拼姐姐,盒子里的徽章是哪一种。但是因为盲盒总量有 105 这么多,小拼姐姐可记不住每只盒子里装的是什么,于是你就被请来写个程序帮小拼姐姐回复这种信息。

输入格式:

输入第一行给出 2 个正整数,分别为盲盒总量 N(≤105)和货栈容量 S(≤100)。接下来一行给出 N 只盒子的编号,编号由 5 位数字组成,给出的顺序是空盒进入传送带的顺序。随后 N/S(保证是整数)行,每行给出一批 S 枚徽章的类型,为 1-9 的数字,给出的顺序是从进货口入栈的顺序。

再下面给出一个正整数 K(≤104),为查询次数。随后 K 行,每行给出一个 5 位编号。

输出格式:

对每个查询编号,在一行中输出该盒子中装的徽章类型。如果编号是错误的,则在一行中输出 Wrong Number

输入样例:

10 5
00132 10093 92001 23333 66666 88888 09009 34658 82750 69251
1 2 3 4 5
9 8 7 6 1
5
66666
88888
69251
55555
10093

输出样例:

1
1
9
Wrong Number
4
//这道题也没什么难度
//简单点来讲就是传送带是队列,出货口是栈
//我们采用map方式储存,简单的很
#include<iostream>
#include<stack>
#include<map>
using namespace std;
int main(){
    map<string,int> m;
    stack<int> s;
    string manghe[100000];
    int n,S;
    cin>>n>>S;
    for(int i=0;i<n;i++){
        cin>>manghe[i];
    }
    int k=0;//盲盒下标
    for(int i=0;i<n/S;i++){
        for(int j=0;j<S;j++){
            int x;
            cin>>x;
            s.push(x);
        }
        for(int j=0;j<S;j++){
            m[manghe[k++]]=s.top();
            s.pop();
        }
    }
    cin>>k;
    for(int i=0;i<k;i++){
        string x;
        cin>>x;
        if(m.find(x)!=m.end())
            cout<<m[x]<<endl;
        else
            cout<<"Wrong Number"<<endl;
    }
}

 

L4-205 浪漫侧影

分数 35

全屏浏览

切换布局

作者 陈越

单位 浙江大学

v.JPG

“侧影”就是从左侧或者右侧去观察物体所看到的内容。例如上图中男生的侧影是从他右侧看过去的样子,叫“右视图”;女生的侧影是从她左侧看过去的样子,叫“左视图”。

520 这个日子还在打比赛的你,也就抱着一棵二叉树左看看右看看了……

我们将二叉树的“侧影”定义为从一侧能看到的所有结点从上到下形成的序列。例如下图这棵二叉树,其右视图就是 { 1, 2, 3, 4, 5 },左视图就是 { 1, 6, 7, 8, 5 }。

fig.JPG

于是让我们首先通过一棵二叉树的中序遍历序列和后序遍历序列构建出一棵树,然后你要输出这棵树的左视图和右视图。

输入格式:

输入第一行给出一个正整数 N (≤20),为树中的结点个数。随后在两行中先后给出树的中序遍历和后序遍历序列。树中所有键值都不相同,其数值大小无关紧要,都不超过 int 的范围。

输出格式:

第一行输出右视图,第二行输出左视图,格式如样例所示。

输入样例:

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

输出样例:

R: 1 2 3 4 5
L: 1 6 7 8 5
#include<stdio.h>
#include<stdlib.h>
typedef struct treenode* node;
struct treenode{
    int val;
    node left;
    node right;
};

node gettree(int a[],int b[],int sum){
    //这边解释一下,传入的数组实际上是整个数组的一部分
    //sum呢是你所求树的节点个数
    //我们的首要任务是找到每个子树的根节点
    int i;
    node bt;
    if(sum==0)
         return NULL;
    else{
        bt=(node)malloc(sizeof(struct treenode));
        bt->val=a[sum-1];
        for(i=0;i<sum;i++){
            if(b[i]==a[sum-1])
                break;
        }
        bt->left=gettree(a,b,i);
        bt->right=gettree(a+i,b+i+1,sum-i-1);
    }
    return bt;
}

void cengxu1(node BT,int n){//左边
     if(!BT)
        return;
    int len=1;
    int pos;
    node a[20],b[20];
    a[0]=BT;
    printf(" %d",a[0]->val);
    while(1){
        if(len==0)
            return;
        pos=0;
        for(int i=0;i<len;i++){
            if(a[i]->left!=NULL)//如果它的左节点不为空,就存到b数组里
                b[pos++]=a[i]->left;
            if(a[i]->right!=NULL)//如果它的右节点不为空,就存到b数组里
                b[pos++]=a[i]->right;
            if(a[i]->right==NULL&&a[i]->left==NULL)
                continue;
        }
        if(pos!=0)
        printf(" %d",b[0]->val);
        len=pos;//为下一次循环做准备
        //更新数组走下一次层序
        for(int i=0;i<len;i++)
            a[i]=b[i];
    }
}

void cengxu2(node BT,int n){//右边
     if(!BT)
        return;
    int len=1;
    int pos;
    node a[20],b[20];
    a[0]=BT;
    printf(" %d",a[0]->val);
    while(1){
        if(len==0)
            return;
        pos=0;
        for(int i=0;i<len;i++){
            if(a[i]->left!=NULL)//如果它的左节点不为空,就存到b数组里
                b[pos++]=a[i]->left;
            if(a[i]->right!=NULL)//如果它的右节点不为空,就存到b数组里
                b[pos++]=a[i]->right;
            if(a[i]->right==NULL&&a[i]->left==NULL)
                continue;
        }
        if(pos!=0)
        printf(" %d",b[pos-1]->val);
        len=pos;//为下一次循环做准备
        //更新数组走下一次层序
        for(int i=0;i<len;i++)
            a[i]=b[i];
    }
}

int main(){
    int n;
    scanf("%d",&n);
    int a[20];//后序
    int b[20];//先序
    for(int i=0;i<n;i++){
        scanf("%d",&b[i]);
    }
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    node root=gettree(a,b,n);
    // 树已经构建完毕,打印的话其实很简单,层序不就好了???
    //有些时候我觉得自己就是个sb
    printf("R:");
    cengxu2(root,n);
    printf("\n");
    printf("L:");
    cengxu1(root,n);
}

 这道题写复杂了,大家看个乐呵就好了

L4-301 狼人杀

分数 80

全屏浏览

切换布局

作者 陈越

单位 浙江大学

以下文字摘自《灵机一动·好玩的数学》:“狼人杀”游戏分为狼人、好人两大阵营。在一局“狼人杀”游戏中,1号玩家说:“2号是狼人”,2号玩家说:“3号是好人”,3号玩家说:“4号是狼人”,4号玩家说:“5号是好人”,5号玩家说:“4号是好人”。已知这5名玩家中有2人扮演狼人角色,有2人说的不是实话,有狼人撒谎但并不是所有狼人都在撒谎。扮演狼人角色的是哪两号玩家?

本题是这个问题的升级版:已知 N 名玩家中有 M 人扮演狼人角色,有 L 人说的不是实话,有狼人撒谎但并不是所有狼人都在撒谎。要求你找出扮演狼人角色的是哪几号玩家?

输入格式:

输入在第一行中给出三个正整数 N、M、L,其中 5 ≤ N ≤ 100,2 ≤ M,L < N。随后 N 行,第 i 行给出第 i 号玩家说的话(1 ≤ i ≤ N),即一个玩家编号,用正号表示好人,负号表示狼人。

输出格式:

如果有解,在一行中按递减顺序输出 M 个狼人的编号,其间以空格分隔,行首尾不得有多余空格。如果解不唯一,则输出最大序列解 —— 即对于两个序列 A = { a[1], ..., a[M] } 和 B = { b[1], ..., b[M] },若存在 0 ≤ k < M 使得 a[i]=b[i] (i ≤ k),且 a[k+1]>b[k+1],则称序列 A 大于序列 B。若无解则输出 No Solution

输入样例 1:

5 2 2
-2
+3
-4
+5
+4

输出样例 1:

4 1

输入样例 2:

6 2 3
-2
+3
-4
+5
+4
-3

输出样例 2(解不唯一):

6 4

输入样例 3:

6 2 5
-2
+3
-4
+5
+4
+6

输出样例 3:

No Solution
//先写下思路吧,首先找出所有组合
//然后对所有组合进行判别模拟,主要就是最后判断的时候,撒谎的人里必须要有狼人
//且狼人撒谎人数必须要小于等于撒谎总人数并且小于狼人总人数
//由于都走一遍实在是太慢了会有超
//那么我们直接倒着来
//还是会爆
//最后一个办法就是出一个直接判断,不求所有组合数了
//过啦哈哈哈哈哈哈哈哈
#include<iostream>
#include<cmath>
#include<vector>
#include <algorithm>
using namespace std;
int ren[120];
int N,M,L;
int flag=0;
vector<vector<int>> result;//用来储存所有组合数
bool check(int a[],int M,vector<int> lie){
    int lang=0;
    for(auto x:lie){
        if (a[x]==-1){
            lang++;
        }
    }
    if(lang==0){
        return false;
    }
    else if (lang>=M){
        return false;
    }
    else{
        return true;
    }
}


void generateCombinations(vector<int>& combination, int n, int m, int index) {
	if(flag==1)
	return;
    if (m == 0) {
        result.push_back(combination);

        int a[120];
        for(int i=1;i<=N;i++){
            a[i]=1;
        }
        vector<int> lie;
        vector<int> lang;
        for (int num : combination) {
            a[num]=-1;
            lang.push_back(num);
        }
        for(int k=1;k<=N;k++)
                if(ren[k]*a[abs(ren[k])]<0)
                    lie.push_back(k);
        if(lie.size()==L&&check(a,M,lie)){
             for(int i=0;i<lang.size();i++){
               if(i==0)
                   cout<<lang[i];
               else{
                   cout<<' '<<lang[i];
                }
              }
            flag=1;
            }
        return;
    }

    for (int i = index; i >=1; i--) {
        combination.push_back(i);
        generateCombinations(combination, n, m - 1, i-1);
        if(flag==1)
        return ;
        combination.pop_back();
    }
}


int main(){
    cin>>N>>M>>L;
    for(int i=1;i<=N;i++){
        cin>>ren[i];
    }
    vector<int> combination;
    generateCombinations(combination,N,M,N);
    if(flag==0)
    cout<<"No Solution";
}

 

L4-302 拼题A打卡奖励

分数 60

全屏浏览

切换布局

作者 陈越

单位 浙江大学

拼题 A 的教超搞打卡活动,指定了 N 张打卡卷,第 i 张打卡卷需要 mi​ 分钟做完,完成后可获得 ci​ 枚奖励的金币。活动规定每张打卡卷最多只能做一次,并且不允许提前交卷。活动总时长为 M 分钟。请你算出最多可以赢得多少枚金币?

输入格式:

输入首先在第一行中给出两个正整数 N(≤103) 和 M(≤365×24×60),分别对应打卡卷的数量和以“分钟”为单位的活动总时长(不超过一年)。随后一行给出 N 张打卡卷要花费的时间 mi​(≤600),最后一行给出 N 张打卡卷对应的奖励金币数量 ci​(≤30)。上述均为正整数,一行内的数字以空格分隔。

输出格式:

在一行中输出最多可以赢得的金币数量。

输入样例:

5 110
70 10 20 50 60
28 1 6 18 22

输出样例:

40

样例解释:

选择最后两张卷子,可以在 50+60=110 分钟内获得 18+22=40 枚金币。

//这题就是经典的01动归
//但是这题数据太大,容易超时
//原本是打算用时间来作为j列,但是M太大了
//所以我们选择价值来作为列,用最大的价值来求容量
#include<iostream>
#include<cstring>
using namespace std;
const int M=365*24*60,N=1010;
int a[N],w[N];
int dp[300000];
int main(){
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    int n,m,sum = 0;
    cin>>n>>m; 
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++){
        cin>>w[i];
        sum+=w[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=sum;j>=w[i];j--){//简单点来说就是你花的时间越少,才有可能拿到更大的利益
            if(dp[j]>dp[j-w[i]]+a[i]){
                dp[j]=dp[j-w[i]]+a[i];
            }
        }
    }
    for(int i=sum;i>=0;i--){
        if(dp[i]<=m){
            cout<<i;
           break;
        }
    }
} 

 

  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值