• 洛谷刷题(普及-):选数、乒乓球、栈、采药、装箱问题


    记录洛谷刷题qaq


    [NOIP2002 普及组] 选数

    题目描述

    已知 n n n 个整数 x 1 , x 2 , ⋯   , x n x_1,x_2,\cdots,x_n x1,x2,,xn,以及 1 1 1 个整数 k k k k < n kk<n)。从 n n n 个整数中任选 k k k 个整数相加,可分别得到一系列的和。例如当 n = 4 n=4 n=4 k = 3 k=3 k=3 4 4 4 个整数分别为 3 , 7 , 12 , 19 3,7,12,19 3,7,12,19 时,可得全部的组合与它们的和为:

    3 + 7 + 12 = 22 3+7+12=22 3+7+12=22

    3 + 7 + 19 = 29 3+7+19=29 3+7+19=29

    7 + 12 + 19 = 38 7+12+19=38 7+12+19=38

    3 + 12 + 19 = 34 3+12+19=34 3+12+19=34

    现在,要求你计算出和为素数共有多少种。

    例如上例,只有一种的和为素数: 3 + 7 + 19 = 29 3+7+19=29 3+7+19=29

    输入格式

    第一行两个空格隔开的整数 n , k n,k n,k 1 ≤ n ≤ 20 1 \le n \le 20 1n20 k < n kk<n)。

    第二行 n n n 个整数,分别为 x 1 , x 2 , ⋯   , x n x_1,x_2,\cdots,x_n x1,x2,,xn 1 ≤ x i ≤ 5 × 1 0 6 1 \le x_i \le 5\times 10^6 1xi5×106)。

    输出格式

    输出一个整数,表示种类数。

    样例 #1

    样例输入 #1

    4 3
    3 7 12 19
    
    • 1
    • 2

    样例输出 #1

    1
    
    • 1

    提示

    【题目来源】

    NOIP 2002 普及组第二题

    代码如下

    #include 
    #include 
    
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    //判断素数
    
    int sum, m, n, k, num[21], i;//sum是m个数的总数和 ,m表示素数的个数 
    
    int SU(int x){
    	if(x==0||x==1)
    		return 0;
    	for(i = 2;i < x;i++){
    		if(x%i==0){
    			return 0;
    			break;
    		}
    	}
    	if(i>=x)
    		return 1;
    } 
    
    
    //抽数
    void CHOU(int N,int now){//num表示还差num个数到k;now表示现在抽到了第now个数字 
    	if(N==0){
    		m += SU(sum);
    	}
    	else{
    		now++;
    		for(int i = now;i <= n;i++){
    			sum += num[i];
    			N--;
    			CHOU(N,i);
    			sum -= num[i];//这两句是为了清空之前选的那个数(的痕迹)
    			N++;
    		}
    	} 
    	 
    } 
    
    
    int main(int argc, char *argv[]) {
    	while(scanf("%d%d",&n,&k)!=EOF){
    		for(int i = 1;i <= n;i++){
    			scanf("%d",&num[i]);
    		}
    		CHOU(k,0);
    		printf("%d\n",m);
    	} 
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    [NOIP2003 普及组] 乒乓球

    题目背景

    国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中 11 11 11 分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白 11 11 11 分制和 21 21 21 分制对选手的不同影响。在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。

    题目描述

    华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在 11 11 11 分制和 21 21 21 分制下,双方的比赛结果(截至记录末尾)。

    比如现在有这么一份记录,(其中 W \texttt W W 表示华华获得一分, L \texttt L L 表示华华对手获得一分):

    WWWWWWWWWWWWWWWWWWWWWWLW \texttt{WWWWWWWWWWWWWWWWWWWWWWLW} WWWWWWWWWWWWWWWWWWWWWWLW

    11 11 11 分制下,此时比赛的结果是华华第一局 11 11 11 0 0 0 获胜,第二局 11 11 11 0 0 0 获胜,正在进行第三局,当前比分 1 1 1 1 1 1。而在 21 21 21 分制下,此时比赛结果是华华第一局 21 21 21 0 0 0 获胜,正在进行第二局,比分 2 2 2 1 1 1。如果一局比赛刚开始,则此时比分为 0 0 0 0 0 0。直到分差大于或者等于 2 2 2,才一局结束。

    你的程序就是要对于一系列比赛信息的输入( WL \texttt{WL} WL 形式),输出正确的结果。

    输入格式

    每个输入文件包含若干行字符串,字符串有大写的 W \texttt W W L \texttt L L E \texttt E E 组成。其中 E \texttt E E 表示比赛信息结束,程序应该忽略 E \texttt E E 之后的所有内容。

    输出格式

    输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。其中第一部分是 11 11 11 分制下的结果,第二部分是 21 21 21 分制下的结果,两部分之间由一个空行分隔。

    样例 #1

    样例输入 #1

    WWWWWWWWWWWWWWWWWWWW
    WWLWE
    
    • 1
    • 2

    样例输出 #1

    11:0
    11:0
    1:1
    
    21:0
    2:1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    提示

    每行至多 25 25 25 个字母,最多有 2500 2500 2500 行。

    (注:事实上有一个测试点 2501 2501 2501 行数据。)

    【题目来源】

    NOIP 2003 普及组第一题

    代码如下

    #include
    #include
    #include
    #include 
    
    char str[100010];
    int cnt=0;
    
    void show(int n){
    
        int a=0,b=0;
        for(int i=0;i<cnt;i++){
            if(str[i]=='W') a++;
            if(str[i]=='L') b++;
    
            if((a>=n||b>=n)&&abs(a-b)>=2){
                printf("%d:%d\n",a,b); 
                a=b=0;
            }
        }
    
        //新的一轮刚开始,或上一局没有打完
        printf("%d:%d\n",a,b); 
    }
    
    int main(){
        char ch;
    
        while(scanf("%c",&ch)&&ch!='E'){
            if(ch=='W'||ch=='L'){
              str[cnt++]=ch;
            }
        }
    
        show(11);
        printf("\n");
        show(21);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    [NOIP2003 普及组] 栈

    题目背景

    栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。

    栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 push(将一个元素进栈)。

    栈的重要性不言自明,任何一门数据结构的课程都会介绍栈。宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙。

    题目描述

    宁宁考虑的是这样一个问题:一个操作数序列, 1 , 2 , … , n 1,2,\ldots ,n 1,2,,n(图示为 1 到 3 的情况),栈 A 的深度大于 n n n

    现在可以进行两种操作,

    1. 将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的 push 操作)
    2. 将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的 pop 操作)

    使用这两种操作,由一个操作数序列就可以得到一系列的输出序列,下图所示为由 1 2 3 生成序列 2 3 1 的过程。

    (原始状态如上图所示)

    你的程序将对给定的 n n n,计算并输出由操作数序列 1 , 2 , … , n 1,2,\ldots,n 1,2,,n 经过操作可能得到的输出序列的总数。

    输入格式

    输入文件只含一个整数 n n n 1 ≤ n ≤ 18 1 \leq n \leq 18 1n18)。

    输出格式

    输出文件只有一行,即可能输出序列的总数目。

    样例 #1

    样例输入 #1

    3
    
    • 1

    样例输出 #1

    5
    
    • 1

    提示

    【题目来源】

    NOIP 2003 普及组第三题

    代码如下

    #include
    #include
    #include
    #include 
    
    
    long n,f[20][20];
    long dfs(int x,int y){
    
        if(f[x][y]!=0) return f[x][y];//记忆化,走过的方案直接调用
        if(x==0) return 1;//当操作队列里没有了,就只有一种方案了
        if(y>0) f[x][y]+=dfs(x,y-1);//栈里不为空的时候才可以把栈里的元素推出
        f[x][y]+=dfs(x-1,y+1);//操作队列里元素减一,栈里元素加一
        return f[x][y];//返回方案值
    }
    int main()
    {
        scanf("%d",&n);
        printf("%lld\n",dfs(n,0));
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    [NOIP2005 普及组] 采药

    题目描述

    辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”

    如果你是辰辰,你能完成这个任务吗?

    输入格式

    第一行有 2 2 2 个整数 T T T 1 ≤ T ≤ 1000 1 \le T \le 1000 1T1000)和 M M M 1 ≤ M ≤ 100 1 \le M \le 100 1M100),用一个空格隔开, T T T 代表总共能够用来采药的时间, M M M 代表山洞里的草药的数目。

    接下来的 M M M 行每行包括两个在 1 1 1 100 100 100 之间(包括 1 1 1 100 100 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

    输出格式

    输出在规定的时间内可以采到的草药的最大总价值。

    样例 #1

    样例输入 #1

    70 3
    71 100
    69 1
    1 2
    
    • 1
    • 2
    • 3
    • 4

    样例输出 #1

    3
    
    • 1

    提示

    【数据范围】

    • 对于 30 % 30\% 30% 的数据, M ≤ 10 M \le 10 M10
    • 对于全部的数据, M ≤ 100 M \le 100 M100

    【题目来源】

    NOIP 2005 普及组第三题

    代码如下

    #include
    #include
    #include
    #include 
    
    int max(int i,int j)
    {
    	if(i > j)
    		return i;
    	else
    		return j;
    }
    int w[105], val[105];
    int dp[1005];
    int main()
    {
        int t,m,res=-1;    
        scanf("%d%d",&t,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&w[i],&val[i]);
        }
        for(int i=1;i<=m;i++) 
        {
            for(int j=t;j>=0;j--) 
            {
                if(j>=w[i])
                {
                    dp[j]=max(dp[j-w[i]]+val[i], dp[j]);
                }
            }
        }    
        printf("%d",dp[t]);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    [NOIP2001 普及组] 装箱问题

    题目描述

    有一个箱子容量为 V V V,同时有 n n n 个物品,每个物品有一个体积。

    现在从 n n n 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小。输出这个最小值。

    输入格式

    第一行共一个整数 V V V,表示箱子容量。

    第二行共一个整数 n n n,表示物品总数。

    接下来 n n n 行,每行有一个正整数,表示第 i i i 个物品的体积。

    输出格式

    • 共一行一个整数,表示箱子最小剩余空间。

    样例 #1

    样例输入 #1

    24
    6
    8
    3
    12
    7
    9
    7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    样例输出 #1

    0
    
    • 1

    提示

    对于 100 % 100\% 100% 数据,满足 0 < n ≤ 30 00<n30 1 ≤ V ≤ 20000 1 \le V \le 20000 1V20000

    【题目来源】

    NOIP 2001 普及组第四题

    代码如下

    #include
    #include
    #include
    #include 
    
    int m,n;                //m即箱子容量V
    int f[20010];
    int w[40];
    int main(){
        int i,j;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&w[i]);
        }
        for(int i=1;i<=n;i++)
    	{
            for(int j= m; j>=w[i];j--)
    		{                           // 注意:这里必须是从m到w[i],否则一个物体会被多次装入箱子,见例1
                if(f[j]<f[j-w[i]]+w[i]){
                    f[j]=f[j-w[i]]+w[i];
                }
            }
        }
        printf("%d\n",m-f[m]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    阿里5年经验之谈 —— 记录一次jmeter压测的过程!
    星球作业(第十期)Android中的ClassLoader
    【Git】Git分布式版本控制工具
    RabbitMQ消息队列的工作模式
    【Spring Security】请求莫名重定向至login的问题
    向日葵远程控制为何采用BGP服务器?自动最优路线、跨运营商高速传输
    React中ref的使用方法和使用场景(详解)
    学习JavaScript进阶
    【自动化营销】跨境电商高效进行WhatsApp营销技巧!
    golang运行期间重新加载环境变量
  • 原文地址:https://blog.csdn.net/weixin_62529383/article/details/126892396