前言

  感觉稍微有些滑稽吧,毕竟每次练的题都是提高组难度的,结果最后的主要任务是普及组抱一个一等奖回来。至于我的分数嘛。。还是在你看完题解后写在[后记]里面。废话不多说,开始题解。

  (其实这篇博客只有题解没有心得。)



  第一题可以说的内容不是很多吧。直接暴力,计算每种铅笔需要花费的金额。

  只不过计算的时候,需要注意如下问题

  • 如果不是整数倍,除完后要加1
  • 神奇的Linux系统,很多人的第三个点wa了,所以要养成良好的编写代码的习惯

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cmath>
  7. #include<algorithm>
  8. #include<stack>
  9. #include<set>
  10. #include<map>
  11. #include<queue>
  12. using namespace std;
  13. typedef bool boolean;
  14. #define smin(a, b) (a) = min((a), (b))
  15. #define smax(a, b) (a) = max((a), (b))
  16. template<typename T>
  17. inline void readInteger(T& u){
  18. char x;
  19. int aFlag = ;
  20. while(!isdigit((x = getchar())) && x != '-');
  21. if(x == '-'){
  22. aFlag = -;
  23. x = getchar();
  24. }
  25. for(u = x - ''; isdigit((x = getchar())); u = u * + x - '');
  26. ungetc(x, stdin);
  27. u *= aFlag;
  28. }
  29.  
  30. int n;
  31. int cost[], num[];
  32. int result;
  33.  
  34. inline void init(){
  35. result = 0xfffffff;
  36. readInteger(n);
  37. for(int i = , b; i <= ; i++){
  38. b = ;
  39. readInteger(num[i]);
  40. readInteger(cost[i]);
  41. b = n / num[i];
  42. if(n % num[i] != ) b += ;
  43. smin(result, b * cost[i]);
  44. }
  45. printf("%d", result);
  46. }
  47.  
  48. int main(){
  49. freopen("pencil.in", "r", stdin);
  50. freopen("pencil.out", "w", stdout);
  51. init();
  52. return ;
  53. }


  第二题,暴力也不会TLE,所以就从起始日期枚举到结束日期,中途把进位之类的事情做好,问题就不会很大。

  只不过仍然会存在一些问题

  • 进位应该从低位开始判断
  • 注意进位的边界

  如果不小心手抽了,有些日期跳过了,或者有些地方出了点问题,变成了死循环,也很麻烦。

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cmath>
  7. #include<algorithm>
  8. #include<stack>
  9. #include<set>
  10. #include<map>
  11. #include<queue>
  12. using namespace std;
  13. typedef bool boolean;
  14. #define smin(a, b) (a) = min((a), (b))
  15. #define smax(a, b) (a) = max((a), (b))
  16. template<typename T>
  17. inline void readInteger(T& u){
  18. char x;
  19. int aFlag = ;
  20. while(!isdigit((x = getchar())) && x != '-');
  21. if(x == '-'){
  22. aFlag = -;
  23. x = getchar();
  24. }
  25. for(u = x - ''; isdigit((x = getchar())); u = u * + x - '');
  26. ungetc(x, stdin);
  27. u *= aFlag;
  28. }
  29.  
  30. typedef class MyDate{
  31. public:
  32. int year;
  33. int month;
  34. int days;
  35. MyDate(){}
  36. MyDate(int num){
  37. days = num % , num /= ;
  38. month = num % , num /= ;
  39. year = num;
  40. }
  41. boolean isHuiWen(){
  42. if((year / ) != (days % )) return false;
  43. if(((year / ) % ) != ((days / ) % )) return false;
  44. if(((year / ) % ) != (month % )) return false;
  45. if((year % ) != ((month / ) % )) return false;
  46. return true;
  47. }
  48. void next(){
  49. days++;
  50. if(month == && days == && (year % != && (year % == || year % == ))){
  51. days = ;
  52. month++;
  53. }else if(month == && days == && (!(year % != && (year % == || year % == )))){
  54. days = ;
  55. month++;
  56. }else if(days == && (month == || month == || month == || month == || month == || month == || month == )){
  57. days = ;
  58. month++;
  59. }else if(days == && (month == || month == || month == || month == )){
  60. days = ;
  61. month++;
  62. }
  63. if(month == ){
  64. month = ;
  65. year++;
  66. }
  67. }
  68. boolean operator !=(MyDate another){
  69. return !(this->days == another.days && this->month == another.month && this->year == another.year);
  70. }
  71. }MyDate;
  72.  
  73. MyDate start;
  74. MyDate _end;
  75.  
  76. inline void init(){
  77. int a, b;
  78. readInteger(a);
  79. readInteger(b);
  80. start = MyDate(a);
  81. _end = MyDate(b);
  82. }
  83.  
  84. inline void solve(){
  85. int result = ;
  86. while(start != _end){
  87. if(start.isHuiWen()) result++;
  88. start.next();
  89. }
  90. if(_end.isHuiWen()) result++;
  91. printf("%d", result);
  92. }
  93.  
  94. int main(){
  95. freopen("date.in", "r", stdin);
  96. freopen("date.out", "w", stdout);
  97. init();
  98. solve();
  99. return ;
  100. }

[小结]

  这道题的难度不是特别难,但是,有个很明显的问题代码不简洁,而且好像读入优化也没什必要。。

明明70几行可以打完的程序,我却偏偏打了100行。

  如果是C语言用户,可以手打一些函数来代替我写的成员函数



  第三题是暴力加优化。

  首先讲思路吧。从头到尾扫描。需要一些量比如说上一艘船,对于它来说,在24小时内最早的一艘的位置(数组中)(就记为last吧)。还有当前不同种类的游客。还需要统计每个国籍的游客的数量(在这艘船的24小时内)

处理一艘船的时候,解决如下几个任务

  1. 更新对于已经不在24小时内的船,从last开始while循环,减去它们对应的国籍的游客数,再判断它是否为0,如果是,那么就把当前不同国籍的数量减去1
  2. 读入该艘船上的游客,如果这个国籍的数量为0,则把当前不同国籍的数量数加1,接着把这个国籍的游客数加1
  3. 输出这个不同国籍的数量

关于还省内存的事再说一下

  1. 使用vector
  2. 用两个一维数组,一个记录每艘船记录的数据在另一个数组中结束的下标,另一个就记录每艘船的游客的国籍

  由于vector太慢(虽说对于这道题已经足够了),而且经常手抖导致崩掉,果断嫌弃,改用方法2(我也不是说vector一定不好,至少对于很多时候还是挺管用的,效率也没有我说的那么糟糕,只不过我不喜欢而已)

  当然现在我很喜欢用vector偷懒  ——2018.2.13

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cmath>
  7. #include<algorithm>
  8. #include<stack>
  9. #include<set>
  10. #include<map>
  11. #include<queue>
  12. #include<vector>
  13. using namespace std;
  14. typedef bool boolean;
  15. #define smin(a, b) (a) = min((a), (b))
  16. #define smax(a, b) (a) = max((a), (b))
  17. template<typename T>
  18. inline void readInteger(T& u){
  19. char x;
  20. int aFlag = ;
  21. while(!isdigit((x = getchar())) && x != '-');
  22. if(x == '-'){
  23. aFlag = -;
  24. x = getchar();
  25. }
  26. for(u = x - ''; isdigit((x = getchar())); u = u * + x - '');
  27. ungetc(x, stdin);
  28. u *= aFlag;
  29. }
  30.  
  31. #define DAYSEC 86400
  32.  
  33. int n;
  34. int tbegin;
  35. int *times;
  36. int listofx[];
  37. int counter[];
  38. int defkinds;
  39. int *endsindex;
  40.  
  41. inline void init(){
  42. readInteger(n);
  43. endsindex = new int[(const int)(n + )];
  44. times = new int[(const int)(n + )];
  45. tbegin = ;
  46. endsindex[] = ;
  47. for(int i = , peo; i <= n; i++){
  48. readInteger(times[i]);
  49. while(times[tbegin] <= times[i] - DAYSEC){
  50. for(int j = endsindex[tbegin - ] + ; j <= endsindex[tbegin]; j++){
  51. counter[listofx[j]]--;
  52. if(counter[listofx[j]] <= ) defkinds--;
  53. }
  54. tbegin++;
  55. }
  56. readInteger(peo);
  57. endsindex[i] = endsindex[i - ] + peo;
  58. for(int j = endsindex[i - ] + ; j <= endsindex[i]; j++){
  59. readInteger(listofx[j]);
  60. if(counter[listofx[j]] == ) defkinds++;
  61. counter[listofx[j]]++;
  62. }
  63. printf("%d\n", defkinds);
  64. }
  65. }
  66.  
  67. int main(){
  68. freopen("port.in", "r", stdin);
  69. freopen("port.out", "w", stdout);
  70. init();
  71. return ;
  72. }


  首先呢,想一个正确但不高效的方法,枚举a,b,c,d然后判断是否存在,理论复杂度O(m4)。

  接着可以发现一个物体的魔法值为2,还有一个魔法值为2,它们的贡献(实在找不到词了),是一样的。所以可以直接枚举数值,并且统计了数量后,可以O(1)判断d是否存在,复杂度降为O(4n3m)

  看着4m有些不爽,决定把它优化掉。既然魔法值一样的物品贡献一样就没必要按照每件来记录作为A、B、C、D物品的次数,直接按照数值来记录,就没有必要去用第四重循环了。

  计算的方法是这样的作为a物品的次数,根据乘法原理,就要加上可作为b物品、c物品和d物品的个数的乘积。没怎么说清楚,但是举个例子就好懂,比如说有1,5,24,26,26。当1作为a物品时,可作为b物品的是5,有一个,可作为c物品的是24,有一个,可作为d物品的是26,有两个,所以应该增加1*1*2次。其他同理。

  为了对付极端数据(不过貌似没有),所以我拍了序,加了个lower_bound,然后并没有AC(滑稽)

  1. #include<iostream>
  2. #include<fstream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cmath>
  7. #include<algorithm>
  8. #include<stack>
  9. #include<set>
  10. #include<map>
  11. #include<queue>
  12. #include<ctime>
  13. using namespace std;
  14. typedef bool boolean;
  15. #define smin(a, b) (a) = min((a), (b))
  16. #define smax(a, b) (a) = max((a), (b))
  17. template<typename T>
  18. inline void readInteger(T& u){
  19. char x;
  20. int aFlag = ;
  21. while(!isdigit((x = getchar())) && x != '-');
  22. if(x == '-'){
  23. aFlag = -;
  24. x = getchar();
  25. }
  26. for(u = x - ''; isdigit((x = getchar())); u = u * + x - '');
  27. ungetc(x, stdin);
  28. u *= aFlag;
  29. }
  30.  
  31. int n, m;
  32. int counter[];
  33. vector<int> poses[];
  34. int *fora, *forb, *forc, *ford;
  35. int *mlist;
  36. int *blist;
  37.  
  38. int mylower_bound(int* a, int from, int end, int val){
  39. int l = from, r = end - ;
  40. while(l <= r){
  41. int mid = (l + r) >> ;
  42. if(val <= a[mid]) r = mid - ;
  43. else l = mid + ;
  44. }
  45. return r + ;
  46. }
  47.  
  48. inline void init(){
  49. readInteger(n);
  50. readInteger(m);
  51. fora = new int[(const int)(n + )];
  52. forb = new int[(const int)(n + )];
  53. forc = new int[(const int)(n + )];
  54. ford = new int[(const int)(n + )];
  55. mlist = new int[(const int)(m + )];
  56. blist = new int[(const int)(m + )];
  57. memset(fora, , sizeof(int) * (n + ));
  58. memset(forb, , sizeof(int) * (n + ));
  59. memset(forc, , sizeof(int) * (n + ));
  60. memset(ford, , sizeof(int) * (n + ));
  61. for(int i = , a; i <= m; i++){
  62. readInteger(a);
  63. counter[a]++;
  64. poses[a].push_back(i);
  65. mlist[i] = blist[i] = a;
  66. }
  67. }
  68.  
  69. inline void solve(){
  70. sort(mlist + , mlist + m + );
  71. for(int i = ; i < n; i++){
  72. if(!counter[i]) continue;
  73. for(int j = i + ; j <= n; j += ){
  74. if(!counter[j]) continue;
  75. int k_start = mylower_bound(mlist, , m + , j + (j - i) * + );
  76. if(k_start == m + ) continue;
  77. for(int k = mlist[k_start]; k <= n; k++){
  78. if(!counter[k]) continue;
  79. int end = k + (j - i) / ;
  80. if(end > n) break;
  81. if(counter[end]){
  82. fora[i] += counter[j] * counter[k] * counter[end];
  83. forb[j] += counter[i] * counter[k] * counter[end];
  84. forc[k] += counter[i] * counter[j] * counter[end];
  85. ford[end] += counter[i] * counter[j] * counter[k];
  86. }
  87. }
  88. }
  89. }
  90. for(int i = ; i <= m; i++){
  91. printf("%d %d %d %d\n", fora[blist[i]], forb[blist[i]], forc[blist[i]], ford[blist[i]]);
  92. }
  93. }
  94.  
  95. int main(){
  96. freopen("magic.in", "r", stdin);
  97. freopen("magic.out", "w", stdout);
  98. init();
  99. solve();
  100. return ;
  101. }

85分比赛时写的程序

  正解呢就是很神奇的方法来做的,首先看张图

  设c,d之间的差为i,则可以表示为上图。总长度大于9i。如果我们设这个长度是9i + 1,那么看,下图

  a2 - a1 = 1。那么c1,d1可以和a1,b1组合,说明c2,d2也可以和a1,b1组合,也就是说,在计算c,d的时候,只需要累加a,b搭配的方案数,再按照乘法原理就可以求出来了。枚举的量也大大减少了,只需要枚举i和d,a。时间复杂度成功地降为可以接受的范围。

Code(看了正解后写出来的程序)

  1. #include<iostream>
  2. #include<fstream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<cmath>
  7. #include<algorithm>
  8. #include<stack>
  9. #include<set>
  10. #include<map>
  11. #include<queue>
  12. #include<ctime>
  13. using namespace std;
  14. typedef bool boolean;
  15. #define smin(a, b) (a) = min((a), (b))
  16. #define smax(a, b) (a) = max((a), (b))
  17. template<typename T>
  18. inline void readInteger(T& u){
  19. char x;
  20. int aFlag = ;
  21. while(!isdigit((x = getchar())) && x != '-');
  22. if(x == '-'){
  23. aFlag = -;
  24. x = getchar();
  25. }
  26. for(u = x - ''; isdigit((x = getchar())); u = u * + x - '');
  27. ungetc(x, stdin);
  28. u *= aFlag;
  29. }
  30.  
  31. int n, m;
  32. int counter[];
  33. int *fora, *forb, *forc, *ford;
  34. int *mlist;
  35. int *blist;
  36.  
  37. int mylower_bound(int* a, int from, int end, int val){
  38. int l = from, r = end - ;
  39. while(l <= r){
  40. int mid = (l + r) >> ;
  41. if(val <= a[mid]) r = mid - ;
  42. else l = mid + ;
  43. }
  44. return r + ;
  45. }
  46.  
  47. inline void init(){
  48. readInteger(n);
  49. readInteger(m);
  50. fora = new int[(const int)(n + )];
  51. forb = new int[(const int)(n + )];
  52. forc = new int[(const int)(n + )];
  53. ford = new int[(const int)(n + )];
  54. mlist = new int[(const int)(m + )];
  55. blist = new int[(const int)(m + )];
  56. memset(fora, , sizeof(int) * (n + ));
  57. memset(forb, , sizeof(int) * (n + ));
  58. memset(forc, , sizeof(int) * (n + ));
  59. memset(ford, , sizeof(int) * (n + ));
  60. for(int i = , a; i <= m; i++){
  61. readInteger(a);
  62. counter[a]++;
  63. mlist[i] = blist[i] = a;
  64. }
  65. }
  66.  
  67. inline void solve(){
  68. // sort(mlist + 1, mlist + m + 1);
  69. for(int i = ; i * < n; i++){
  70. int len = * i + ;
  71. int s = ;
  72. for(int d = len + ; d <= n; d++){
  73. s += counter[d - len] * counter[d - len + i * ];
  74. ford[d] += s * counter[d - i];
  75. forc[d - i] += s * counter[d];
  76. }
  77. s = ;
  78. for(int a = n - len; a >= ; a--){
  79. s += counter[a + len] * counter[a + len - i];
  80. fora[a] += s * counter[a + i * ];
  81. forb[a + i * ] += s * counter[a];
  82. }
  83. }
  84. for(int i = ; i <= m; i++){
  85. printf("%d %d %d %d\n", fora[blist[i]], forb[blist[i]], forc[blist[i]], ford[blist[i]]);
  86. }
  87. }
  88.  
  89. int main(){
  90. freopen("magic.in", "r", stdin);
  91. freopen("magic.out", "w", stdout);
  92. init();
  93. solve();
  94. return ;
  95. }

PS


后话

  从上面的描述中应该可以猜到我noip普及组的分数了吧。我也就不说了。

  怎么说呢。。这也算是一个里程碑吧!虽然oi的路还长。。但是小小地庆祝一下也是可以的。

这次考得比较好的原因主要是心态比较好吧。也感谢四川吧,分数线比起什么浙江300分好多了(真的没有别的意思),所以说压力没那么大,而且靠差了还有提高组

noip2016普及组题解和心得的更多相关文章

  1. [题解]noip2016普及组题解和心得

    [前言] 感觉稍微有些滑稽吧,毕竟每次练的题都是提高组难度的,结果最后的主要任务是普及组抱一个一等奖回来.至于我的分数嘛..还是在你看完题解后写在[后记]里面.废话不多说,开始题解. 第一题可以说的内 ...

  2. noip2016普及组 题解

    T1 大水题,不解释 上考场代码 #include <algorithm> #include <cstdio> using namespace std; int main() ...

  3. NOIP2016普及组解题报告

    概述 \(NOIP2016\)普及组的前三题都比较简单,第四题也有很多的暴力分,相信参加了的各位\(OIer\)在\(2016\)年都取得了很好的成绩. 那么,我将会分析\(NOIP2016\)普及组 ...

  4. NOIP2008普及组题解

    NOIP2008普及组题解 从我在其他站的博客直接搬过来的 posted @ 2016-04-16 01:11 然后我又搬回博客园了233333 posted @ 2016-06-05 19:19 T ...

  5. NOIP2016普及组复赛解题报告

    提高组萌新,DAY1DAY2加起来骗分不到300,写写普及组的题目聊以自慰. (附:洛谷题目链接 T1:https://www.luogu.org/problem/show?pid=1909 T2:h ...

  6. NOIP2002-2017普及组题解

    虽然普及组一般都是暴力省一,但是有一些题目还是挺难的qwq个人觉得能进TG的题目会在前面打上'*' NOIP2002(clear) #include<bits/stdc++.h> usin ...

  7. 【做题记录】[NOIP2016 普及组] 魔法阵

    P2119 魔法阵 2016年普及组T4 题意: 给定一系列元素 \(\{X_i\}\) ,求满足以下不等式的每一个元素作为 \(a,b,c,d\) 的出现次数 . \[\begin{cases}X_ ...

  8. NOIP2016普及组

    普及组.代码有空发. 第一题就是买铅笔.暴力模拟绝对可取. 第二题就是回文日期.从t1的年份到t2的年份枚举每一年.头尾要特判. 第三题就是海港.骗了40分. 第四题就是魔法阵.不太好优化. 完.

  9. NOIP2008普及组 题解 -SilverN

    T1 ISBN号码 题目描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符, 其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔符( ...

随机推荐

  1. php iconv() : Detected an illegal character in input string

    php iconv() : Detected an illegal character in input string_php技巧_脚本之家 https://www.jb51.net/article/ ...

  2. python脚本中为什么要在目录前加一个r

    目的:为了避免转义,r后面的内容,全文输出: r是保持字符串原始值的意思,就是说不对其中的符号进行转义.因为windows下的目录字符串中通常有斜杠"\",比如,windows下的 ...

  3. navicat的安装

    1.首先在官网下载navicat,具体安装步骤比较简单,下一步下一步即可. 2.安装之后,按照下面的网址做法激活 http://www.jianshu.com/p/b1f9194e1e31 3.教程: ...

  4. servlet输出请求头

    1.参考 Enumeration headerNames = req.getHeaderNames(); while(headerNames.hasMoreElements()) { String h ...

  5. mysql 内置功能 触发器 实验

    #准备表命令表 CREATE TABLE cmd ( id INT PRIMARY KEY auto_increment, ), priv ), cmd ), sub_time datetime, # ...

  6. CSS表格(未完成)

    CSS 表格 使用 CSS 可以使 HTML 表格更美观. 表格边框 指定CSS表格边框,使用border属性. 下面的例子指定了一个表格的Th和TD元素的黑色边框:

  7. [LeetCode] 252. Meeting Rooms_Easy tag: Sort

    Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si ...

  8. python基础24 -----python中的各种锁

    一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...

  9. mysql查询表基本操作

    数据库表的创建create table <表名>( <列名> <数据类型及长度> [not null], <列名> <数据类型及长度>, . ...

  10. JSP—中文乱码

    中文乱码问题? --------------------------------------- 不乱码的条件: 1.JSP页面本身的编码 pageEncoding UTF-8 (把jsp页面翻译成ja ...