NOIP2017普及组复赛解题报告
2017-12-11 16:59
866 查看
这次考试在衢州二中,这里地形太复杂了,离开考前3分钟才找到考场。无语·········所以一开考就没有好心情。这次的题目相对来以往的前几道题比较简单,但最后一道题比较难,考场上只想出来了50分的代码。
时间限制:1s 内存限制:256M
AC记录
超级水题,NOIP史上最简单的题没有之一,只要c++如果入门的都会做,普通的运算符操作
难度:☆☆☆☆☆ (入门难度)
民间数据:100分
官方得分:100分
这道题对于c++的选手有一个无法避免的误差,就是使用浮点数(float || double)是直接*0.3会出现t.9999999999········的情况。e.g. :10.0*0.3=2.9999999·····
这导致一些选手出现 printf (”%d”,int (ans))使结果少一,60分
AC记录
这道题其实也不难,暴力的时间复杂度也只有O(n*q)==O(1000000),而且图书编码与需求码都用 int 存的下,唯一的难点就是判断末尾是否相等,需要一定的代码能力
难度:★☆☆☆☆ (普及-)
难点:check 处理
民间数据:100分
官方成绩:100分
这道题可以有变式,就是将字典编码长度与查询码长度最大为100(注意是长度,不是数值),这样对于排序就有点难了。
AC记录
难度:★★☆☆☆ (普及刚好)
民间数据:100分
官方数据:100分
这道题代码量还是挺大的,考试时用记忆化搜索做的,但据说最好的解决方案是广度优先搜索,但我的方法也AC了,记忆化搜索相对来说好写一点但是,需要很细心,在考场上
AC记录
50分记录
20分记录
第一眼看到数据大小就想到了二分答案,然后在check函数中就想到了用动态规划(DP)来做,但这是O(N^2)的算法肯定会超时,但得50分已经可以了,但二分写错了,这是最恶心的地方,只得了20分
标准程序是用二分答案+单调队列来做的,略微超纲了,那是提高组的算法,是比较难理解的
难度:★★★★☆ (提高+)
民间数据:20分
官方得分:20分
20分代码
50分代码
AC代码 单调队列
时间限制:1s 内存限制:256M
第一题:成绩 score
题目AC记录
超级水题,NOIP史上最简单的题没有之一,只要c++如果入门的都会做,普通的运算符操作
难度:☆☆☆☆☆ (入门难度)
民间数据:100分
官方得分:100分
#include<bits/stdc++.h> using namespace std; int a,b,c; int ans; int main() { freopen ("score.in","r",stdin); freopen ("score.out","w",stdout); scanf ("%d %d %d",&a,&b,&c); ans=a/5+b/10*3+c/2; printf ("%d",ans); return 0; }
这道题对于c++的选手有一个无法避免的误差,就是使用浮点数(float || double)是直接*0.3会出现t.9999999999········的情况。e.g. :10.0*0.3=2.9999999·····
这导致一些选手出现 printf (”%d”,int (ans))使结果少一,60分
第二题:图书管理员 librarian
题目AC记录
这道题其实也不难,暴力的时间复杂度也只有O(n*q)==O(1000000),而且图书编码与需求码都用 int 存的下,唯一的难点就是判断末尾是否相等,需要一定的代码能力
难度:★☆☆☆☆ (普及-)
难点:check 处理
民间数据:100分
官方成绩:100分
#include<bits/stdc++.h> using namespace std; int n,q; int a[1010]; int main() { freopen ("librarian.in","r",stdin); freopen ("librarian.out","w",stdout); scanf ("%d%d",&n,&q); for (int i=1;i<=n;i++) scanf ("%d",&a[i]); sort (a+1,a+n+1); //c++ STL for (int i=1;i<=q;i++) { int l,x; bool flag=0; scanf ("%d %d",&l,&x); int t=pow (10,l); //计算t 即末尾0的个数 for (int i=1;i<=n;i++) if ((a[i]-x)%t==0) //重点:若x是a[i]的位数,那么(a[i]-x)%t==0 { flag=1; printf ("%d\n",a[i]); break; } if (!flag) printf ("-1\n"); } return 0; }
这道题可以有变式,就是将字典编码长度与查询码长度最大为100(注意是长度,不是数值),这样对于排序就有点难了。
第三题:棋盘 chess
题目AC记录
难度:★★☆☆☆ (普及刚好)
民间数据:100分
官方数据:100分
这道题代码量还是挺大的,考试时用记忆化搜索做的,但据说最好的解决方案是广度优先搜索,但我的方法也AC了,记忆化搜索相对来说好写一点但是,需要很细心,在考场上
#include<bits/stdc++.h> using namespace std; int minn[110][110][2]; int n,m,ans=10000; int a[110][110]; void DFS (int x,int y,int cos,bool way,int c) { if (minn[x][y][c]<=cos) return; minn[x][y][c]=cos; if (x==m&&y==m) { ans=min (ans,cos); return; } if (c==a[x+1][y]) DFS (x+1,y,cos,1,c); else if (a[x+1][y]!=-1) DFS (x+1,y,cos+1,1,a[x+1][y]); else if (way) { if (c==1) { DFS (x+1,y,cos+2,0,1); DFS (x+1,y,cos+< 4000 span class="hljs-number">3,0,0); } else { DFS (x+1,y,cos+2,0,0); DFS (x+1,y,cos+3,0,1); } } if (c==a[x-1][y]) DFS (x-1,y,cos,1,c); else if (a[x-1][y]!=-1) DFS (x-1,y,cos+1,1,a[x-1][y]); else if (way) { if (c==1) { DFS (x-1,y,cos+2,0,1); DFS (x-1,y,cos+3,0,0); } else { DFS (x-1,y,cos+2,0,0); DFS (x-1,y,cos+3,0,1); } } if (c==a[x][y+1]) DFS (x,y+1,cos,1,c); else if (a[x][y+1]!=-1) DFS (x,y+1,cos+1,1,a[x][y+1]); else if (way) { if (c==1) { DFS (x,y+1,cos+2,0,1); DFS (x,y+1,cos+3,0,0); } else { DFS (x,y+1,cos+2,0,0); DFS (x,y+1,cos+3,0,1); } } if (c==a[x][y-1]) DFS (x,y-1,cos,1,c); else if (a[x][y-1]!=-1) DFS (x,y-1,cos+1,1,a[x][y-1]); else if (way) { if (c==1) { DFS (x,y-1,cos+2,0,1); DFS (x,y-1,cos+3,0,0); } else { DFS (x,y-1,cos+2,0,0); DFS (x,y-1,cos+3,0,1); } } } int main() { freopen ("chess.in","r",stdin); freopen ("chess.out","w",stdout); memset (minn,-1,sizeof (minn)); memset (a,-1,sizeof (a)); scanf ("%d%d",&m,&n); for (int i=1;i<=n;i++) { int x,y,c; scanf ("%d%d%d",&x,&y,&c); a[x][y]=c; } for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) { minn[i][j][0]=10000; minn[i][j][1]=10000; } DFS (1,1,0,1,a[1][1]); if (ans==10000) { printf ("-1"); return 0; } printf ("%d",ans); return 0; }
第四题:跳房子 jump
题目AC记录
50分记录
20分记录
第一眼看到数据大小就想到了二分答案,然后在check函数中就想到了用动态规划(DP)来做,但这是O(N^2)的算法肯定会超时,但得50分已经可以了,但二分写错了,这是最恶心的地方,只得了20分
标准程序是用二分答案+单调队列来做的,略微超纲了,那是提高组的算法,是比较难理解的
难度:★★★★☆ (提高+)
民间数据:20分
官方得分:20分
20分代码
#include<bits/stdc++.h> using namespace std; int n,d,k; int x[500010],s[500010]; int sum=0,ans; bool check (int u) { int f[500010]; memset (f,0,sizeof (f)); f[0]=0; int ans=-1000000010; for (int i=0;i<=n;i++) { int l1=x[i]+d-u; if (l1<=x[i]) l1=x[i]+1; int r1=x[i]+d+u; if (r1>=x ) r1=x ; for (int j=i+1;j<=n;j++) if (x[j]>=l1&&x[j]<=r1) { f[j]=max (f[j],f[i]+s[j]); ans=max (ans,f[j]); } } if (ans>=k) return 1; else return 0; } int main() { //freopen ("jump.in","r",stdin); //freopen ("jump.out","w",stdout); scanf ("%d%d%d",&n,&d,&k); x[0]=0; for (int i=1;i<=n;i++) { scanf ("%d%d",&x[i],&s[i]); if (s[i]>0) sum+=s[i]; } if (sum<k) { printf ("-1"); return 0; } int l=0,r=1000000010; while (l<r) { int mid=(l+r)/2; if (check (mid)) { r=mid-1; ans=mid; } else l=mid+1; } printf ("%d",ans); return 0; }
50分代码
#include<bits/stdc++.h> using namespace std; int n,d,k; int x[500010],s[500010]; int sum=0,ans; int f[500010]; bool check (int u) { memset (f,0,sizeof (f)); f[0]=0; int ans=-1000000010; for (int i=0;i<=n;i++) { int l1=x[i]+d-u; if (l1<=x[i]) l1=x[i]+1; int r1=x[i]+d+u; if (r1>=x ) r1=x ; for (int j=i+1;j<=n;j++) if (x[j]>=l1&&x[j]<=r1) { f[j]=max (f[j],f[i]+s[j]); ans=max (ans,f[j]); if (ans>=k) return 1; } } if (ans>=k) return 1; else return 0; } int main() { //freopen ("jump.in","r",stdin); //freopen ("jump.out","w",stdout); scanf ("%d%d%d",&n,&d,&k); x[0]=0; for (int i=1;i<=n;i++) { scanf ("%d%d",&x[i],&s[i]); if (s[i]>0) sum+=s[i]; } if (sum<k) { printf ("-1"); return 0; } int l=0,r=1000000010; while (l<r) { int mid=(l+r)/2; if (check (mid)) r=mid; else l=mid+1; } printf ("%d",l); return 0; }
AC代码 单调队列
#include<bits/stdc++.h> using namespace std; struct node{ int x,v; }q[500005]; int f[500005]; long long maxx=0; int n,d,k; int dis[500005],sc[500005]; bool check (int g) { int low=max (1,d-g),high=d+g; int cur=0,head=0,tail=-1; memset (f,0,sizeof (f)); for (int i=1;i<=n;i++) { for (;cur<i&&dis[cur]<=dis[i]-low;cur++) { while (head<=tail&&q[tail].v<f[cur]) tail--; if (f[cur]!=-0x3f3f3f3f) q[++tail].v=f[cur],q[tail].x=dis[cur]; } while (head<=tail&&dis[i]-q[head].x>high) head++; f[i]=(head<=tail)?q[head].v+sc[i]:-0x3f3f3f3f; if (f[i]>=k) return 1; } return 0; } int main() { scanf ("%d%d%d",&n,&d,&k); for (int i=1;i<=n;i++) { scanf ("%d%d",&dis[i],&sc[i]); maxx+=max (sc[i],0); } if (maxx<k) { printf ("-1"); return 0; } int l=1,r=dis ; while (l<r) { int mid=(l+r)/2; if (check (mid)) r=mid; else l=mid+1; } printf ("%d",l); return 0; }
相关文章推荐
- NOIP2004普及组复赛解题报告
- 2008年NOIP普及组复赛解题报告
- NOIP2016普及组复赛解题报告
- NOIP2016普及组复赛解题报告
- NOIP2012普及组复赛解题报告
- NOIP2017普及组解题报告
- NOIP2014普及组复赛子矩阵解题报告
- NOIP2008 普及组T2 排座椅 解题报告-S.B.S
- NOIP 2007 普及组解题报告
- 全国信息学奥林匹克联赛(NOIP2010)复赛 1.数字统计 解题报告
- 全国信息学奥林匹克联赛(NOIP2010)复赛 3.导弹拦截 解题报告
- NOIP2017普及组复赛总结
- NOIP2008 普及组T2 排座椅 解题报告-S.B.S
- 纪中训练 day8 【NOIP普及组】模拟赛D组 解题报告
- NOIP 2007 普及组解题报告--…
- NOIP2015普及组第四题解题报告
- 纪中训练 day3 【NOIP普及组】模拟赛D组 解题报告
- NOIP2008 普及组T1 ISBN号码 解题报告-S.B.S.
- NOIP2017 提高Day2-2 宝藏 解题报告
- NOIP 1998 普及组 2的幂次方 解题报告