noip2016普及组题解报告
来源:互联网 发布:直播间软件 编辑:程序博客网 时间:2024/06/06 19:12
当这份卷骗分拿了320分后,我不得不由衷地感叹一句:今年前两题简直太太太太太太太太太太太太太水了!如果你这张卷连200分都没有,我只想说,你还是去OJ上刷一刷Hello,World!和A+B Problem吧!
第一题:pencil AC >=O(1)
题目描述
P老师需要去商店买n支铅笔作为小朋友们参加NOIP的礼物。她发现商店一共有 3种包装的铅笔,不同包装内的铅笔数量有可能不同,价格也有可能不同。为了公平起 见,P老师决定只买同一种包装的铅笔。
商店不允许将铅笔的包装拆开,因此P老师可能需要购买超过n支铅笔才够给小朋 友们发礼物。
现在P老师想知道,在商店每种包装的数量都足够的情况下,要买够至少n支铅笔最少需要花费多少钱。
输入输出格式
输入格式:
输入的第一行包含一个正整数n,表示需要的铅笔数量。
接下来三行,每行用两个正整数描述一种包装的铅笔:其中第一个整数表 示这种包装内铅笔的数量,第二个整数表示这种包装的价格。
保证所有的7个数都是不超过10000的正整数。
输出格式:
输出一行一个整数,表示P老师最少需要花费的钱。
输入输出样例
输入样例#1:
57
2 2
50 30
30 27
输出样例#1:
54
输入样例#2:
9998
128 233
128 2333
128 666
输出样例#2:
18407
输入样例#3:
9999
101 1111
1 9999
1111 9999
输出样例#3:
89991
说明
铅笔的三种包装分别是:
•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。
【子任务】
子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试 只解决一部分测试数据。
每个测试点的数据规模及特点如下:
上表中“整倍数”的意义为:若为“K”,表示对应数据所需要的铅笔数量n—定是每种包装铅笔数量的整倍数(这意味着一定可以不用多买铅笔)。
好吧,我相信这题不用题解,直接上代码:
//pencil.cpp Noip2016 Junior Problem A#include <cstdio>int n, a[10], b[10];int min(int a, int b){ return a<b ? a : b;}int main(){// freopen("pencil.in","r",stdin);// freopen("pencil.out","w",stdout); scanf("%d", &n); for (int i = 1; i <= 3; i++) scanf("%d %d", &a[i], &b[i]); int res[5]; for (int i = 1; i <= 3; i++) { if (n%a[i] == 0) res[i] = (n / a[i])*b[i]; else if (n <= a[i]) res[i] = b[i]; else res[i] = ((n / a[i]) + 1)*b[i]; } printf("%d", min(res[1], min(res[2], res[3])));// fclose(stdin); fclose(stdout); return 0;}
第二题:date AC O(n)
题目描述
在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。
牛牛习惯用8位数字表示一个日期,其中,前4位代表年份,接下来2位代表月 份,最后2位代表日期。显然:一个日期只有一种表示方法,而两个不同的日期的表 示方法不会相同。
牛牛认为,一个日期是回文的,当且仅当表示这个日期的8位数字是回文的。现 在,牛牛想知道:在他指定的两个日期之间包含这两个日期本身),有多少个真实存 在的日期是回文的。
一个8位数字是回文的,当且仅当对于所有的i ( 1 <=i<= 8 )从左向右数的第i个 数字和第9-i个数字(即从右向左数的第i个数字)是相同的。
例如:
•对于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。
也是水题!
根据数据分析,这题直接暴力枚举能AC,于是我就打了下面的代码。。。
程序一发下来,我拿到洛谷上测,居然真的没有TLE,我可是一点优化都没打的呀!
//date.cpp Noip2016 Junior Problem B#include <iostream>#include <cstdio>using namespace std;bool run(int b) //判断是不是闰年{ if (b % 4 == 0 && (b % 100 != 0 || b % 400 == 0)) return true; return false;}int date1, date2, ans = 0;bool hui() //判断是不是回文数{ if (date1 / 10000000 == date1 % 10 && (date1 / 1000000) % 10 == (date1 % 100) / 10 && (date1 / 100000) % 10 == (date1 % 1000) / 100 && (date1 / 10000) % 10 == (date1 % 10000) / 1000) //尿性所致 return 1; return 0;}void jia() //将日期加1天,我也懒得做优化了{ int nian = (date1 - date1 % 10000) / 10000, yue = (date1 % 10000) / 100, re = (date1 % 100); switch (yue) { case 1:case 3:case 5:case 7:case 8:case 10: if (re<31) re++; else { re = 1; yue++; } break; case 12: if (re<31) re++; else { nian++; yue = 1; re = 1; } break; case 4:case 6:case 9:case 11: if (re<30) re++; else { yue++; re = 1; } break; case 2: if (re<28) re++; else { if (run(nian) && re<29) re++; else { yue++; re = 1; } } break; } date1 = nian * 10000 + yue * 100 + re;}int main(){// freopen("date.in","r",stdin);// freopen("date.out","w",stdout); cin >> date1 >> date2; if (date1 == date2) //题目数据显示60% date1=date2 { if (hui()) cout << 1; else cout << 0; return 0; } while (date1 <= date2) { if (hui()) ans++; jia(); //本来if(hui) 可以直接加一年的 } cout << ans; fclose(stdin); fclose(stdout); return 0;}
第三题:port TLE(70) O(n^3)
题目描述
小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)中,总共有多少个不同的数。
输入输出格式
输入格式:
第一行输入一个正整数n,表示小K统计了 n艘船的信息。
接下来n行,每行描述一艘船的信息:前两个整数ti和ki分别表示这艘船到达海港的时间和船上的乘客数量,接下来ki个整数x(i,j)表示船上乘客的国籍。
保证输入的ti是递增的,单位是秒;表示从小K第一次上班开始计时,这艘船在第 ti 秒到达海港。
保证:
1<=n<=100000,
∑ki<=3*100000,
1<=x[i][j]<=100000,
1<=t[i-1]<=ti<=10^9
其中∑ki表示所有的ki的和。
输出格式:
输出n行,第i行输出一个整数表示第i艘船到达后的统计信息。
输入输出样例
输入样例#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】
第一艘船在第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个不同 的国家。
【样例解释2】
第一艘船在第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个不同的国家。
【数据范围】
好吧,我选择了70%(实战经验还不足!)
直接枚举!!!!
//port.cpp Noip2016 Junior Problem C#include <cstdio>#include <iostream>#include <cstring>#define maxn 10002using namespace std;const int tl = 86400;int n, t[maxn], k[maxn], te = 1, book[maxn], x[maxn][maxn];int main(){// freopen("port.in","r",stdin);// freopen("port.out","w",stdout); cin >> n; for (int i = 1; i <= n; i++) { memset(book, 0, sizeof(book)); int res = 0; cin >> t[i] >> k[i]; for (int j = 1; j <= k[i]; j++) cin >> x[i][j]; for (int j = te; j <= i; j++) if (t[i] - t[j]<tl) for (int l = 1; l <= k[j]; l++) { if (book[x[j][l]] == 0) { book[x[j][l]] = 1; res++; } } else te = j + 1; cout << res; if (i != n) cout << endl; }// fclose(stdin); fclose(stdout); return 0;}
//正解在这里!花了半小时才想出来//port(new).cpp Noip2016 Junior Problem C#include <cstdio>#include <iostream>#include <queue>using namespace std;struct visitor //结构体储存旅客信息{ int time, country; visitor operator = (const visitor& x) { time = x.time; country = x.country; return *this; }};queue <visitor> boat; //创建队列int n, t, k, ans = 0, book[100001];int main(){// freopen("port.in", "r", stdin);// freopen("port.out", "w", stdout); cin >> n; for (int i = 0; i < n; i++) { cin >> t >> k; for (int j = 0; j < k; j++) { visitor x; int c; cin >> c; x.time = t; x.country = c; if (!book[c]) ans++; boat.push(x); book[c]++; } visitor q = boat.front(); while (q.time <= t - 86400) { book[q.country]--; if (!book[q.country]) ans--; boat.pop(); q = boat.front(); } cout << ans << endl; }// fclose(stdin); fclose(stdout); return 0;}
第四题:magic TLE(50) O(n^4)
题目描述
六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量。
大魔法师有m个魔法物品,编号分别为1,2,…,m。每个物品具有一个魔法值,我们用Xi表示编号为i的物品的魔法值。每个魔法值Xi是不超过n的正整数,可能有多个物品的魔法值相同。
大魔法师认为,当且仅当四个编号为a,b,c,d的魔法物品满足xa
//magic.cpp Noip2016 Junior Problem D#include <iostream>#include <algorithm>#include <cstdio>using namespace std;int main(){// freopen("magic.in","r",stdin);// freopen("magic.out","w",stdout); int n, m, x[40005], a, b, c, d, res[40005][5]; cin >> n >> m; for (int i = 0; i<m; i++) cin >> x[i]; for (a = 0; a < m; a++) for (b = 0; b < m; b++) if (x[a] < x[b]) for (c = 0; c<m; c++) if (x[b] < x[c] && x[b] - x[a] < (float(x[c] - x[b])) / 3) for (d = 0; d<m; d++) if (x[c]<x[d] &&x[b] - x[a] == 2 * (x[d] - x[c])) { res[a][1]++; res[b][2]++; res[c][3]++; res[d][4]++; } for (int i = 0; i<m; i++) { for (int j = 1; j<5; j++) { cout << res[i][j]; if (j != 4) cout << ' '; } if (i != m - 1) cout << '\n'; }// fclose(stdin); fclose(stdout); return 0;}//正解如下://magic.cpp noip2016 Junior Problem D#include <cstdio>int n, m, i, j, x, y, s[40005], f[40005], a[40005], b[40005], c[40005], d[40005];int main(){ scanf("%d %d", &n, &m); for (i = 1; i <= m; i++) { scanf("%d", &s[i]); f[s[i]]++; } for (i = 1; i <= n / 9; i++) { x = 9 * i + 1; y = 0; for (j = 9 * i + 2; j <= n; j++) { y = y + f[j - x] * f[j - x + 2 * i]; d[j] += y*f[j - i]; c[j - i] += y*f[j]; } x = 8 * i + 1; y = 0; for (j = n - 9 * i - 1; j >= 1; j--) { y += f[j + x] * f[j + x + i]; a[j] += y*f[j + 2 * i]; b[j + 2 * i] += y*f[j]; } } for (i = 1; i < m; i++) printf("%d %d %d %d\n", a[s[i]], b[s[i]], c[s[i]], d[s[i]]); printf("%d %d %d %d", a[s[i]], b[s[i]], c[s[i]], d[s[i]]);}
- noip2016普及组题解报告
- noip2016普及组 题解
- NOIP2016 普及组南海区模拟题解题报告
- noip2016普及组复赛题解
- NOIP2016 普及组 解题报告
- noip2016提高&普及组简要题解
- NOIP2016普及组 第四题 题解
- NOIP2016普及组[魔法阵]题解
- NOIP2016普及组复赛解题报告
- NOIP2016普及组复赛解题报告
- NOIP2016普及组T3海港解题报告
- NOIP2016 普及组第四题 魔法阵magic 题解
- NOIP2016 普及组 总结+题目吐槽+代码+简单题解
- NOIP2015普及组第四题解题报告
- NOIP2016普及组T1买铅笔解题报告
- c++回文日期【NOIP2016普及组】解题报告
- 【蒻爆了的NOIP系列--普及组复赛】(7)NOIP2016普及组复赛题解
- NOIP2016普及组 总结
- 快速排序算法-C语言实现
- ==和equal区别
- spring笔记总结2
- HDU 2167 Pebbles 状压
- bzoj 2212: [Poi2011]Tree Rotations 线段树合并
- noip2016普及组题解报告
- 静态根据代码的顺序
- canvas画线API实现简单地图
- UVALive 7505 Hungry Game of Ants (2015Ecfinal)
- 51nod 1085 背包问题【01背包】
- 复杂ListView的多条目类型复用
- Android高效加载大图、多图解决方案,有效避免程序OOM
- Android安全机制探讨
- awk脚本实现wordcount