一、题目及分析
买铅笔
题目描述
P老师需要去商店买n支铅笔作为小朋友们参加NOIP的礼物。她发现商店一共有 3种包装的铅笔,不同包装内的铅笔数量有可能不同,价格也有可能不同。为了公平起 见,P老师决定只买同一种包装的铅笔。
商店不允许将铅笔的包装拆开,因此P老师可能需要购买超过n支铅笔才够给小朋友们发礼物。
现在P老师想知道,在商店每种包装的数量都足够的情况下,要买够至少n支铅笔*最少*需要花费多少钱。
输入格式:
输入的第一行包含一个正整数n,表示需要的铅笔数量。
接下来三行,每行用两个正整数描述一种包装的铅笔:其中第一个整数表示这种包装内铅笔的数量,第二个整数表示这种包装的价格。
保证所有的7个数都是不超过10000的正整数。
输出格式:
输出一行一个整数,表示P老师最少需要花费的钱。
样例1输入:
57
2 2
50 30
30 27
样例1输出:
54
说明
铅笔的三种包装分别是:
•2支装,价格为2;
•50支装,价格为30
;•30支装,价格为27。
P老师需要购买至少57支铅笔。
如果她选择购买第一种包装,那么她需要购买29份,共计2x29 = 58支,需要花费的钱为2x29 = 58。
实际上,P老师会选择购买第三种包装,这样需要买2份。虽然最后买到的铅笔数 量更多了,为30x2 = 60支,但花费却减少为27 x2 = 54,比第一种少。
对于第二种包装,虽然每支铅笔的价格是最低的,但要够发必须买2份,实际的 花费达到了 30 x 2 = 60,因此P老师也不会选择。所以最后输出的答案是54。
样例2输入:
9998
128 233
128 2333
128 666
样例2输出:
18407
样例3输入:
9999
101 1111
1 9999
1111 9999
样例3输出:
89991
【子任务】子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解决一部分测试数据。每个测试点的数据规模及特点如下表:
上表中“整倍数”的意义为:若为“V”,表示对应数据所需要的铅笔数量n一定是每种包装铅笔数量的整倍数(这意味着一定可以不用多买铅笔)。
分析:
这道题比较简单,直接用除法,再向上取整,乘上单价,找出最小的数。
#include
#include
int main()
{
int n,i,x,y,sum=1<<30,a,b;
scanf("%d",&n);
for(i=1;i<=3;i++){
scanf("%d%d",&x,&y);
if(x!=0){
a=int(1.0*n/x+0.9999999);
b=a*y;
if(b
例如:
•对于2016年11月19日,用8位数字20161119表示,它不是回文的。
•对于2010年1月2日,用8位数字20100102表示,它是回文的。
•对于2010年10月2日,用8位数字20101002表示,它不是回文的。
每一年中都有12个月份:
其中,1、3、5、7、8、10、12月每个月有31天;4、6、9、11月每个月有30天;而对于2月,闰年时有29天,平年时有28天。
一个年份是闰年当且仅当它满足下列两种情况其中的一种:
1.这个年份是4的整数倍,但不是100的整数倍;
2.这个年份是400的整数倍。
例如:
•以下几个年份都是闰年:2000、2012、2016。
•以下几个年份是平年:1900、2011、2014。
输入格式:
输入包括两行,每行包括一个8位数字。第一行表示牛牛指定的起始日期。第二行表示牛牛指定的终止日期。保证date_i和都是真实存在的日期,且年份部分一定为4位数字,且首位数字不为0。
保证date1 —定不晚于date2。
输出格式:
输出一行,包含一个整数,表示在date1和date2之间,有多少个日期是回文的。
样例1输入:
20110101
20111231
样例1输出:
1
样例2输入:
20000101
20101231
样例2输出:
2
【样例说明】
对于样例1,符合条件的日期是20111102。
对于样例2,符合条件的日期是20011002和20100102。
【子任务】
对于60%的数据,满足date1 = date2。
分析:
最开始觉得是一道很坑的题目,就只判断了date1=date2的情况,后来发现可以直接枚举年数,结果忘了判断闰年,
可能要错一个点,要是考试时把“28”写成“29”就好了。。。(希望数据水一点)
#include
#include
int mon[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};//就是这里
int main()
{
char a[15],b[15];
int i,j,f,sf,x,y,z,w,month,day,sum=0;
scanf("%s\n%s",a,b);
f=0;
for(i=0;i<8;i++){
if(a[i]!=b[i]){
f=1;
break;
}
}
if(f==0){
sf=0;
for(i=0;i<8;i++){
if(a[i]!=a[7-i]){
sf=1;
break;
}
}
if(sf==0){
printf("1");
return 0;
}
else{
printf("0");
return 0;
}
}
else{
x=1000*(a[0]-48)+100*(a[1]-48)+10*(a[2]-48)+a[3]-48;
z=1000*(a[4]-48)+100*(a[5]-48)+10*(a[6]-48)+a[7]-48;
y=1000*(b[0]-48)+100*(b[1]-48)+10*(b[2]-48)+b[3]-48;
w=1000*(b[4]-48)+100*(b[5]-48)+10*(b[6]-48)+b[7]-48;
for(i=x;i<=y;i++){
if(i%10<2){
month=i%10*10+i/10%10;
day=i/100%10*10+i/1000%10;
if(month<=12){
if(mon[month]>=day){
if(i==x){
if(100*month+day>=z)
sum++;
}
else if(i==y){
if(100*month+day<=w)
sum++;
}
else sum++;
}
}
}
}
printf("%d",sum);
}
}
小K是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客。
小K对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况;对于第i艘到达的船,他记录了这艘船到达的时间ti (单位:秒),船上的乘 客数星ki,以及每名乘客的国籍 x(i,1), x(i,2),…,x(i,k);。
小K统计了n艘船的信息,希望你帮忙计算出以每一艘船到达时间为止的24小时(24小时=86400秒)内所有乘船到达的乘客来自多少个不同的国家。
形式化地讲,你需要计算n条信息。对于输出的第i条信息,你需要统计满足 ti - 86400 < tp <= ti的船只p,在所有的x(p,j)中,总共有多少个不同的数。
样例1输入:
3
1 4 4 1 2 2
2 2 2 3
10 1 3
样例1输出:
3
4
4
样例2输入:
4
1 4 1 2 2 3
3 2 2 3
86401 2 3 4
86402 1 5
样例2输出:
3
3
3
4
【样例一说明】
第一艘船在第1秒到达海港,最近24小时到达的船是第一艘船,共有4个乘客,分别是来自国家4,1,2,2,共来自3个不同的国家;
第二艘船在第2秒到达海港,最近24小时到达的船是第一艘船和第二艘船,共有 4+2=6个乘客,分别是来自国家4,1,2,2,2,3,共来自4个不同的国家;
第三艘船在第10秒到达海港,最近24小时到达的船是第一艘船、第二艘船和第三艘船,共有4+2+1=7个乘客,分别是来自国家4,1,2,2,2,3,3,共来自4个不同的国家。
【样例二说明】
第一艘船在第1秒到达海港,最近24小时到达的船是第一艘船,共有4个乘客,分别是来自国家1,2,2,3,共来自3个不同的国家。
第二艘船在第3秒到达海港,最近24小时到达的船是第一艘船和第二艘船,共有4+2=6个乘客,分别是来自国家1,2,2,3,2,3,共来自3个不同的国家。
第三艘船在第86401秒到达海港,最近24小时到达的船是第二艘船和第三艘船,共有2+2=4个乘客,分别是来自国家2,3,3,4,共来自3个不同的国家。
第四艘船在第86402秒到达海港,最近24小时到达的船是第二艘船、第三艘船和第四艘船,共有2+2+1=5个乘客,分别是来自国家2,3,3,4,5,共来自4个不同的国家。
分析:
在考试的时候,觉得这道题很坑,结果考完之后才知道是一道水题。
这道题既容易超时,也容易爆内存,最好的方法就是在原来的基础上进行统计。
用一个结构体队列来存一个人的国籍和到达时间,再用一个头指针来判断前面的人到达时间是否超过24小时。
结果我在考试的时候,是用一个vis数组来判重,每次输入一条船,就进行一次判重,最后就超时了。。。
AC代码:
#include
#include
#include
using namespace std;
struct node{
int x,time;
}o,t;
queue a;
int v[100005];
int main()
{
int i,m,j,n,k,s=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d",&t.time,&m);
for(j=1;j<=m;j++){
scanf("%d",&t.x);
a.push(t);
v[t.x]++;
k=max(k,t.x);
if(v[t.x]==1)
s++;
}
o=a.front();
while(t.time-o.time>=86400){
a.pop();
v[o.x]--;
if(!v[o.x])
s--;
o=a.front();
}
printf("%d\n",s);
}
}
魔法阵
样例1输入
30 8
1
24
7
28
5
29
26
24
样例1输出
4 0 0 0
0 0 1 0
0 2 0 0
0 0 1 1
1 3 0 0
0 0 0 2
0 0 2 2
0 0 1 0
【样例解释1】
共有5个魔法阵,分别为:
物品1,3,7,6,其魔法值分别为1,7,26,29;
物品1,5,2,7,其魔法值分别为1,5,24,26;
物品1,5,7,4,其魔法值分别为1,5,26,28;
物品1,5,8,7,其魔法值分别为1,5,24,26;
物品5,3,4,6,其魔法值分别为5,7,28,29。
以物品5为例,它作为A物品出现了1次,作为B物品出现了3次,没有作为C物品或者D物品出现,所以这一行输出的四个数依次为1,3,0,0。
此外,如果我们将输出看作一个m行4列的矩阵,那么每一列上的m个数之和都应等于魔法阵的总数。所以,如果你的输出不满足这个性质,那么这个输出一定不正确。你可以通过这个性质在一定程度上检查你的输出的正确性。
样例2输入
15 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
样例2输出
5 0 0 0
4 0 0 0
3 5 0 0
2 4 0 0
1 3 0 0
0 2 0 0
0 1 0 0
0 0 0 0
0 0 0 0
0 0 1 0
0 0 2 1
0 0 3 2
0 0 4 3
0 0 5 4
0 0 0 5
【子任务】
每个测试点的详细数据范围见下表
分析:
一看这道题,就觉得是一道很水的题,但是看了数据范围就发现这道题很坑,虽然正解是用枚举,但是枚举是有
技巧的。然而............在考试的时候,我用了4个for循环,超时了一堆点。
听说正解是用2个for循环,但是我现在还没有弄明白用2个for循环的思路,如果有哪位大佬知道,请在评论里面说
一下。
二、考后心得
经过了这一次NOIP的考试,我觉得NOIP不会考太难的算法,大部分的题目都是考(思维能力+一些简单算法),
只有后面的3题或4题比较难以外,其它的题目都比较正常,但是在考试的时候一定要仔细,有时候数据很坑,
但是样例很简单,你测样例就测不出程序的BUG,所以你就要多编几组特殊数据,尽量卡爆自己的程序,
这样你就可以找出程序的漏洞,从而改进自己的程序,
如果你发现自己的程序在测极端数据时会超时,就想一下其它的方法,比如说第3题,我没有在原来的基础上进行
统计,就超时了。
一些涉及到思维难度的题目,比如说第4题,如果你实在想不出来改进的思路,就去检查一下前面的题,保证自己
在前面的题目上不丢分。
以上就是我对NOIP考试的心得。