目录
念念不忘,必有回响
最近小编不断的刷题,发现了有一类名称叫NOIP的题目,这类题目相比于常规的牛客网习题是难度更高的,因此小编对于NOIP这个东西抱有很强的好奇心,于是小编就去查了一下,结果大为震惊,原来有的人在高中初中就开始卷了。
NOIP:
全国青少年信息学奥林匹克联赛(National Olympiad in Informatics in Provinces,简称NOIP)自1995年至2020年已举办25次。每年由中国计算机学会统一组织。 NOIP在同一时间、不同地点以各省市为单位由特派员组织。全国统一大纲、统一试卷。初、高中或其他中等专业学校的学生可报名参加联赛。联赛分初赛和复赛两个阶段。初赛考察通用和实用的计算机科学知识,以笔试形式进行。复赛为程序设计,须在计算机上调试完成。参加初赛者须达到一定分数线后才有资格参加复赛。联赛分普及组和提高组两个组别,难度不同,分别面向初中和高中阶段的学生。复赛可使用C、C++、Pascal语言,2022年后将不可使用Pascal、C语言,只能使用C++。
实在是太恐怖了,这些题目都有一定的难度,下面一一来讲解:
[NOIP2008]ISBN号码
这一题,小编最开始想到的办法其实并不是数组,小编对于数字的敏感度很高,换句话说,小编的思维太数学了,小编想的是用模(%)10和除(/)10,不断的实现每一位的数字的乘,然后再一一相加得到最终结果,但是因为最终无法实现字符和sum匹配出正确的Right,后面久久无法解决,最后采取使用数组的方法,错误的代码如下:
#include <stdio.h> int main() { int a, b, c, d; scanf("%d-%d-%d-%d", &a, &b, &c, &d); int sum = a * 1; int i = 4; int j = 9; int ret = b; int temp = c; while (ret != 0) { sum += (ret % 10) * i; i--; ret = ret / 10; } while (temp != 0) { sum += (c % 10) * j; j--; temp = temp / 10; } if (sum % 11 == d) printf("Right"); else if (sum % 11 == 10) printf("%d-%d-%d-X", a, b, c); else printf("%d-%d-%d-%d", a, b, c, sum % 11); return 0; }
但是数组的方法就不会有这样的麻烦,数组通过将13个字符排到数组中,将字符‘-’排除在外然后一一乘对于的数字,唯一值得注意的点就是根据ASCII码表,字符数字变成数字需要减去一个字符‘0’。正确的代码如下:
#include<stdio.h> int main() { char arr[13]; int i, j; scanf("%s",arr); int s = 0; for(i=0, j=1; i<11; i++) { if(arr[i] != '-') { s += (arr[i]-'0')*j; j++; } } int m = s % 11; if(m == arr[12]-'0' || (m == 10 && arr[12] == 'X')) { printf("Right\n"); } else { if(m == 10) { for(i=0; i<12; i++) { printf("%c", arr[i]); } printf("X"); } else{ for(i=0; i<12; i++) { printf("%c", arr[i]); } printf("%d", m); } } }
[NOIP2015]金币
对于这样一个题目,很多小伙伴一看题目,就晕了头,这获得钱的数量和获得固定钱的天数都不固定,这应该如何是好?但是大家仔细想想,小编带着大家分析一下,我们首先创建一个发工资的天数,然后再这个天数里,无论或多或少,国王每天是不是都要给骑士发工资,并且发工资的天数都等于所发工资的值,那我们创建一个循环,其进入循环的条件是当前天数小于发工资,但是我们每天发的工资都不一样,因此我们需要创建第二循环,第一个循环创建一个变量,并初始化为1,作为第二个循环的条件,第二个循环就是应该发这个工资的天数,第二个变量就初始化为0,并条件是小于第一个变量,这样我们的两个循环就建好了,后面只用当当前天数大于发工资的天数的时候,这个时候退出循环,使用一个if语句,然后将每一天的工资相加就是我们所需要的值,正确代码如下:
#include<stdio.h> int main() { int data = 0;//预计天数 int sum = 0; int k = 1;//当前天数 scanf("%d",&data); for(int i = 1;k<=data;i++) { for(int j = 0;j<i;j++) { if(k>data) break; sum+=i; k++; } } printf("%d",sum); return 0; }
[NOIP2018]标题统计
这个题目相比前两个题目而言,是简单一点的,并不需要我们过多的思考,只需要将字符串看成一个字符型数组,其中需要使用gets()函数来吸收空格,不然可能导致程序误判。
正确的代码如下:
#include<stdio.h> #include<string.h> int main(){ int sum=0,i; char s[100]; gets(s);//gets才能吸收空格 for(i=0;i<strlen(s);i++){ if(s[i]>='0'&&s[i]<='9'){ sum++; } if(s[i]>='a'&&s[i]<='z'){ sum++; } if(s[i]>='A'&&s[i]<='Z'){ sum++; } } printf("%d",sum); }
大家可以看到对于高中生,初中生可能有一点困难,但是对于我们大学生来说,刚刚好,小编发现这种题目可以极大程度的开发我们编程潜力,不逼自己一把,都不知道自己可以那么那么的厉害,小编后续还会带来这一期的更新,如果小伙伴们看的满意,给小编一个赞吧!