[关闭]
@wsndy-xx 2019-08-16T22:22:52.000000Z 字数 4452 阅读 744

Noip 2019 冲刺


多做几套模拟题,体会心路历程。


from hzwer模拟赛整理 2014-9-6 NOIP模拟赛
time 08.16
准备拿出 3.5h 做这套题,可是做了 1.5h 就已经完全没有做下去的欲望了。

T1 工资

聪哥在暑假参加了打零工的活动,这个活动分为n个工作日,每个工作日的工资为Vi。有m个结算工钱的时间,聪哥可以自由安排这些时间,也就是说什么时候拿钱,老板说的不算,聪哥才有发言权!(因为聪哥是土豪,他是老板的老板)
聪哥不喜欢身上一次性有太多的钱,于是他想安排一下拿钱的时间,使他一次性拿的钱中最大的最小。(最后一天一定要领钱)
输入
第一行 2个数 n,m
接下来n行,每行一个数,代表Vi.
输出
最小的最大钱数。
数据范围
20% 1<=n<=20
另 20% 1<=n<=50,Vi的和不超过1000
100% 1<=n<=100,000,m<=n,Vi<=10,000

算法分析:
最大值最小,二分答案。
刚刚好,2015年的noip就考了二分答案的题
所以可能这道题在当年应该比现在更有思维难度。

得分分析:
大概在 2min 内得到此题的完整思路,在 10min 左右可以写完代码,在 15min 左右调试完毕。在 45min 左右写完暴力,在 60min 左右拍上。
写暴力的时间比写正解的时间要慢上 30min 是十分正常的,对于这种题目来说。

代码:

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <string>
  6. #include <cstdio>
  7. using namespace std;
  8. const int N = 1e5 + 10;
  9. #define gc getchar()
  10. inline int read() {
  11. int x = 0; char c = gc;
  12. while(c < '0' || c > '9') c = gc;
  13. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
  14. return x;
  15. }
  16. int n, m, a[N];
  17. bool See(int x) {
  18. int use = 0;
  19. for(int i = 1; i <= n; i ++) {
  20. int j = i, now = 0;
  21. while(now + a[j] <= x && j <= n) {
  22. now += a[j];
  23. j ++;
  24. }
  25. i = j - 1;
  26. use ++;
  27. }
  28. return use <= m;
  29. }
  30. int main() {
  31. n = read(), m = read();
  32. int L = 0, R = 1e9, Ans;
  33. for(int i = 1; i <= n; i ++) a[i] = read();
  34. for(int i = 1; i <= n; i ++) L = max(L, a[i]);
  35. while(L <= R) {
  36. int mid = (L + R) >> 1;
  37. if(See(mid)) Ans = mid, R = mid - 1;
  38. else L = mid + 1;
  39. }
  40. cout << Ans;
  41. return 0;
  42. }

T2藏妹子之处

今天CZY又找到了三个妹子,有着收藏爱好的他想要找三个地方将妹子们藏起来,将一片空地抽象成一个R行C列的表格,CZY要选出3个单元格。但要满足如下的两个条件:
(1)任意两个单元格都不在同一行。
(2)任意两个单元格都不在同一列。
选取格子存在一个花费,而这个花费是三个格子两两之间曼哈顿距离的和(如(x1,y1)和(x,y2)的曼哈顿距离为|x1-x2|+|y1-y2|)。狗狗想知道的是,花费在minT到maxT之间的方案数有多少。
答案模1000000007。所谓的两种不同方案是指:只要它选中的单元格有一个不同,就认为是不同的方案。
输入格式:
一行,4个整数,R、C、minT、maxT。3≤R,C≤4000, 1≤minT≤maxT≤20000。

算法分析
题解
from https://www.cnblogs.com/zhber/p/4036003.html
2、发现对于三个点(x1,y1)(x2,y2)(x3,y3),如果任意交换坐标费用不变,即如果换成(x2,y1)(x3,y2)(x1,y3)费用不变
所以题意=枚举3个横坐标和三个纵坐标,算合理的方案数
对于x1,x2,x3 , y1,y2,y3,若有x1 不妨令x1 枚举x1,y1,令s=2(x1+y1)则满足 minT<=2(x3-x1)+2(y3-y1)<=maxT 即(minT+s)/2<=x3+y3<=(maxT+s)/2的(x3,y3)才可以。则(x3,y3)对答案的更新即是(x2,y2)的个数,即(x3-x1-1)(y3-y1-1).这样枚举两个点n^4、TLE……
3、限定x3=k,则(minT+s)/2-k<=y3<=(maxT+s)/2-k.且y1+2<=y3<=c.
第三个点(k,???)对答案的更新是(k-x1-1)
Σ[(minT+s)/2-k-y1-1到(maxT+s)/2-k-y1-1]
令S=(minT+s)/2-y1-1,T=(maxT+s)/2-k-y1-1,则对于x3=k,方案是(k-x1-1)Σ[S-k到T-k]=(k-x1-1)(S-T+1)(S+T-2k)
这样枚举x1,y1,x3,效率n^3、TLE……
4、其实这题跟CQOI2014数三角形很像。(x1,y1)和(x3,y3)构成一个矩形,但是对于一个确定的矩形边框,它的费用是一定的,就是2(x3-x1)+2(y3-y1)即矩形的边长。它对答案的贡献也是一定的,即(x3-x1-1)
(y3-y1-1)。这个矩形在r*c的大矩形中出现的次数也是给定的,设矩形长为x,宽为y,则出现了(r-x+1)*(c-y+1)次。那么直接枚举矩形的边长,然后就可以算出答案。这样n^2

得分分析:
5min 20分

代码

  1. #include<cstdio>
  2. #include<iostream>
  3. #define mod 1000000007
  4. #define LL long long
  5. using namespace std;
  6. LL ans;
  7. int n, m, mx, mn;
  8. int main() {
  9. scanf("%d %d %d %d", &n, &m, &mn, &mx);
  10. for (int i = 3; i <= n; i ++)
  11. for (int j = 3; j <= m; j ++) {
  12. int w = 2 * (i + j - 2);
  13. if (w <= mx && w >= mn) ans += (LL) (n - i + 1) * (m - j + 1) * (i - 2) * (j - 2) % mod;
  14. }
  15. printf("%lld\n", (ans * 6) % mod);
  16. }

T3银河之星

给定初始状态的多枚棋子,每次可以将一枚棋子向八个方向走两个或者走一个,跨过的棋子被消掉,问是否可以只剩下一枚棋子并且该棋子可以到达指定的位置。
棋盘大小 100 *100
初始棋子数目 10

算法分析:
不会做
没题解
凉凉

得分分析:
这种题这不知道该怎么办
暴力都不知道咋写或者说懒得写或者说写也不应定能写出来。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cstdlib>
  5. #include<map>
  6. #include<algorithm>
  7. #define ll long long
  8. #define inf 1000000000
  9. using namespace std;
  10. inline int read() {
  11. int x=0,f=1;
  12. char ch=getchar();
  13. while(ch<'0'||ch>'9') {
  14. if(ch=='-')f=-1;
  15. ch=getchar();
  16. }
  17. while(ch>='0'&&ch<='9') {
  18. x=x*10+ch-'0';
  19. ch=getchar();
  20. }
  21. return x*f;
  22. }
  23. map<ll,int> q;
  24. ll bin[15],bg,ed;
  25. int ans[1005];
  26. int k,n,m,xt,yt,sz;
  27. int xx[4]= {0,1,1,1},yy[4]= {1,-1,0,1};
  28. bool mp[10][10];
  29. void add(int x1,int y1,int x2,int y2) {
  30. x1=(x1+3)%3;
  31. x2=(x2+3)%3;
  32. y1=(y1+3)%3;
  33. y2=(y2+3)%3;
  34. int u=x1*3+y1,v=x2*3+y2;
  35. mp[u][v]=1;
  36. }
  37. void pre() {
  38. int a1,a2,b1,b2;
  39. for(int i=0; i<n; i++)
  40. for(int j=0; j<m; j++)
  41. for(int k=0; k<4; k++) {
  42. a1=i+xx[k],b1=j+yy[k];
  43. a2=a1+xx[k],b2=b1+yy[k];
  44. if(a2+xx[k]<n&&b2+yy[k]<m)add(i,j,a2,b2);
  45. if(a2<n&&b2<m)add(i,j,a1,b1);
  46. }
  47. }
  48. int dfs(ll x) {
  49. if(x==ed)return 1;
  50. int a,b,a1,a2,b1,b2,t;
  51. if(q[x])t=q[x];
  52. else t=q[x]=++sz;
  53. if(ans[t])return ans[t];
  54. for(int i=0; i<3; i++)
  55. for(int j=0; j<3; j++) {
  56. int t=i*3+j;
  57. if(x/bin[t]%11)
  58. for(int k=0; k<4; k++) {
  59. a1=(i+xx[k]+3)%3,b1=(j+yy[k]+3)%3;
  60. a2=(a1+xx[k]+3)%3,b2=(b1+yy[k]+3)%3;
  61. a=a1*3+b1,b=a2*3+b2;
  62. if((x/bin[a]%11)&&mp[t][a])
  63. if(dfs(x-bin[t]-bin[a]+bin[b])==1)return ans[t]=1;
  64. if((x/bin[b]%11)&&mp[t][b])
  65. if(dfs(x-bin[t]-bin[b]+bin[a])==1)return ans[t]=1;
  66. }
  67. }
  68. return ans[t]=-1;
  69. }
  70. int main() {
  71. freopen("galaxy.in","r",stdin);
  72. freopen("galaxy.out","w",stdout);
  73. bin[0]=1;
  74. for(int i=1; i<=10; i++)bin[i]=bin[i-1]*11;
  75. while(scanf("%d%d%d%d%d",&k,&n,&m,&xt,&yt)!=EOF) {
  76. q.clear();
  77. sz=bg=0;
  78. memset(ans,0,sizeof(ans));
  79. memset(mp,0,sizeof(mp));
  80. pre();
  81. xt=(xt+2)%3;
  82. yt=(yt+2)%3;
  83. ed=bin[xt*3+yt];
  84. int x,y,v;
  85. for(int i=1; i<=k; i++) {
  86. x=read();
  87. y=read();
  88. x=(x+2)%3;
  89. y=(y+2)%3;
  90. v=x*3+y;
  91. bg+=bin[v];
  92. }
  93. if(dfs(bg)==1)puts("Yes");
  94. else puts("No");
  95. }
  96. return 0;
  97. }

总结: 得分情况 在 60min + 5min + 0min = 65min 的有效时间内得到了 100 + 20 + 0 = 120分 的成绩。个人认为这套题在与noip题的匹配度上并不大
暴力难度 < noip2018Day1
正解难度本人无法比较,因为实在是实力不允许啊。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注