[关闭]
@wsndy-xx 2018-05-05T11:24:39.000000Z 字数 7431 阅读 990

5月4日 —— hzwer模拟题

                    wsndy

题解

题面

小奇挖矿2(mining)
【题目背景】
小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎。

【问题描述】
现在有 个星球,从左到右标号为 ,小奇最初在 号星球。
处矿体,第 处矿体有 单位原矿,在第 个星球上。
由于飞船使用的是老式的跳跃引擎,每次它只能从第 号星球移动到第 号星球或 号星球。每到一个星球,小奇会采走该星球上所有的原矿,求小奇能采到的最大原矿数量。
注意,小奇不必最终到达 号星球。

【输入格式】
第一行 个整数
接下来 行,每行 个整数

【输出格式】
输出一行一个整数,表示要求的结果。

【样例输入】

  1. 3 13
  2. 100 4
  3. 10 7
  4. 1 11

【样例输出】

  1. 101

【样例解释】
第一次从 ,第二次从 ,总共采到 单位原矿。

【数据范围】
对于20%的数据
对于40%的数据
对于60%的数据
对于100%的数据


小奇的矩阵(matrix)
【题目背景】
小奇总是在数学课上思考奇怪的问题。

【问题描述】
给定一个 的矩阵,矩阵中的每个元素 为正整数。
接下来规定
合法的路径初始从矩阵左上角出发,每次只能向右或向下走,终点为右下角。
路径经过的 个格子中的元素为 的平均数,路径的 值为
值最小的合法路径,输出V值即可,有多组测试数据。

【输入格式】
第一行包含一个正整数 ,表示数据组数。
对于每组数据:
第一行包含两个正整数 ,表示矩阵的行数和列数。
接下来 行,每行 个正整数 ,描述这个矩阵。

【输出格式】
对于每次询问,输出一行一个整数表示要求的结果

【样例输入】

  1. 1
  2. 2 2
  3. 1 2
  4. 3 4

【样例输出】

  1. 14

【数据范围】
对于30%的数据
有另外40%的数据 ,矩阵中的元素不大于
对于100%的数据 ,矩阵中的元素不大于


小奇的仓库(warehouse)
【题目背景】
小奇采的矿实在太多了,它准备在喵星系建个矿石仓库。令它无语的是,喵星系的货运飞船引擎还停留在上元时代!

【问题描述】
喵星系有 个星球,星球以及星球间的航线形成一棵树。
从星球 到星球 要花费 秒。( 表示 间的航线长度, 为位运算中的异或)
为了给仓库选址,小奇想知道,星球 到其它所有星球花费的时间之和。

【输入格式】
第一行包含两个正整数
接下来 行,每行 个正整数 ,表示 之间的航线长度为

【输出格式】
行,每行一个整数,表示星球 到其它所有星球花费的时间之和。

【样例输入】

  1. 4 0
  2. 1 2 1
  3. 1 3 2
  4. 1 4 3

【样例输出】

  1. 6
  2. 8
  3. 10
  4. 12

【数据范围】

测试点编号 N M
1 6 0
2 100 5
3 2000 9
4 50000 0
5 50000 0
6 50000 1
7 50000 6
8 100000 10
9 100000 13
10 100000 15

保证答案不超过


题解

T1

将所有矿物排序, 为到第 个矿体能获得的最大原矿数,那么 ,其中, 满足能拆分成
这样 需要 的复杂度,但是我们发现,相距超过 (Noip 2017 Day1 T1 Woc)的一定可达,那么不超过 的范围内暴力,超过 的取个最大值即可,复杂度
可以把相邻的星球距离超过 的压缩成 ,按照 的 做法
吐槽
竟然只能的 , 位置竟然可以重复,

  1. #include<map>
  2. #include<set>
  3. #include<cmath>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<iostream>
  8. #define inf 1000000000
  9. #define ll long long
  10. using namespace std;
  11. ll read()
  12. {
  13. ll x=0,f=1;char ch=getchar();
  14. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  15. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  16. return x*f;
  17. }
  18. struct data{
  19. int a,b;
  20. friend bool operator<(data a,data b){
  21. return a.a<b.a;
  22. }
  23. }a[100005];
  24. int n,m;
  25. int v[2000005],f[2000005];
  26. int main()
  27. {
  28. memset(f,-1,sizeof(f));
  29. n=read();m=read();
  30. for(int i=1;i<=n;i++)
  31. a[i].b=read(),a[i].a=read();
  32. sort(a+1,a+n+1);
  33. int now=0;
  34. for(int i=1;i<=n;i++)
  35. {
  36. if(a[i].a-a[i-1].a>17)now+=18,v[now]+=a[i].b;
  37. else now+=a[i].a-a[i-1].a,v[now]+=a[i].b;
  38. }
  39. int ans=0;
  40. f[0]=0;
  41. for(int i=0;i<=now;i++)
  42. if(f[i]!=-1)
  43. {
  44. f[i+4]=max(f[i+4],f[i]+v[i+4]);
  45. f[i+7]=max(f[i+7],f[i]+v[i+7]);
  46. ans=max(ans,f[now]);
  47. }
  48. printf("%d\n",ans);
  49. return 0;
  50. }

T2

对于30%的数据,把所有的路径深搜出来取最优,复杂度是

这道题乍一看像是 ,但是问题在于因为求的是方差与平均数有关,每一步的代价似乎不能直接得出

对于另外40%的数据,我们发现路径 不超过 ,考虑枚举 ,平均值为 ,那我们就能得到每一步的代价,但是要保证求的路径符合 和为,设计 表示到 ,和为 的最小代价


复杂度是

事实上,路径 和不等于 也无所谓,因为对于一条路径,只有我们枚举的 等于路径 和时,这条路径的方差才最小

设我们枚举的 比真实的 和小 是任意实数
很容易证明

所以直接去掉 的第一维,复杂度是 ,可以通过100%的数据

  1. #include<map>
  2. #include<set>
  3. #include<cmath>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<iostream>
  7. #define inf 1000000000
  8. #define ll long long
  9. #define N (n+m)*30
  10. using namespace std;
  11. ll read()
  12. {
  13. ll x=0,f=1;char ch=getchar();
  14. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  15. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  16. return x*f;
  17. }
  18. int ans;
  19. int T,n,m;
  20. int a[35][35];
  21. int f[1805][35][35];
  22. void dp()
  23. {
  24. f[a[1][1]][1][1]=a[1][1]*a[1][1];
  25. for(int i=1;i<=n;i++)
  26. for(int j=1;j<=m;j++)
  27. for(int k=0;k<=N;k++)
  28. if(f[k][i][j]!=1000000)
  29. {
  30. int x=i+1,y=j,v=a[x][y];
  31. f[k+v][x][y]=min(f[k+v][x][y],f[k][i][j]+v*v);
  32. x=i,y=j+1,v=a[x][y];
  33. f[k+v][x][y]=min(f[k+v][x][y],f[k][i][j]+v*v);
  34. }
  35. for(int i=1;i<=N;i++)
  36. if(f[i][n][m]!=1000000)
  37. ans=min(ans,(n+m-1)*f[i][n][m]-i*i);
  38. }
  39. int main()
  40. {
  41. T=read();
  42. for(int cas=1;cas<=T;cas++)
  43. {
  44. ans=inf;
  45. n=read();m=read();
  46. for(int i=1;i<=n;i++)
  47. for(int j=1;j<=m;j++)
  48. a[i][j]=read();
  49. for(int i=1;i<=n;i++)
  50. for(int j=1;j<=m;j++)
  51. for(int k=0;k<=N;k++)
  52. f[k][i][j]=1000000;
  53. dp();
  54. printf("%d\n",ans);
  55. }
  56. return 0;
  57. }

T3

,就有10分
的基础上,我们对每条边处理一下 ,就有
简单的树形 ,或者 ,处理完每个点到其它点的最短路后再加上 ,
个点无需 ,那么我们树形 扫一个节点与其它所有节点的路径长度之和,可以合并信息,最终均摊 分。
个点 ,那么我们树形 到一个点时记录有多少个 ,多少个 ,然后每当一条路径到 ,那部分就再记录一个值,分到手。
一样的,就是原来的、大于等于 变成了 么,
为什么 的树剖会

  1. #include<set>
  2. #include<map>
  3. #include<ctime>
  4. #include<queue>
  5. #include<cmath>
  6. #include<cstdio>
  7. #include<vector>
  8. #include<cstring>
  9. #include<cstdlib>
  10. #include<iostream>
  11. #include<algorithm>
  12. #define inf 1000000000
  13. #define pa pair<int,int>
  14. #define ll long long
  15. #define mod 45989
  16. using namespace std;
  17. int read()
  18. {
  19. int x=0,f=1;char ch=getchar();
  20. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  21. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  22. return x*f;
  23. }
  24. int bin[20];
  25. int n,m,cnt;
  26. int dis[100005],last[100005];
  27. int f[100005][16],g[100005],t[16];
  28. struct edge{
  29. int to,next,v;
  30. }e[200005];
  31. void insert(int u,int v,int w)
  32. {
  33. e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
  34. e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w;
  35. }
  36. void dfs1(int x,int fa)
  37. {
  38. for(int i=last[x];i;i=e[i].next)
  39. if(e[i].to!=fa)
  40. {
  41. dfs1(e[i].to,x);
  42. g[x]+=g[e[i].to]+e[i].v/16;
  43. f[x][e[i].v%16]++;
  44. for(int j=0;j<16;j++)
  45. {
  46. int k=j+e[i].v;
  47. g[x]+=k/16*f[e[i].to][j];
  48. f[x][k%16]+=f[e[i].to][j];
  49. }
  50. }
  51. }
  52. void dfs2(int x,int fa)
  53. {
  54. for(int i=last[x];i;i=e[i].next)
  55. if(e[i].to!=fa)
  56. {
  57. int tmp=g[x]-g[e[i].to];
  58. for(int j=0;j<16;j++)
  59. {
  60. int k=j+e[i].v;
  61. tmp-=k/16*f[e[i].to][j];
  62. t[k%16]=f[x][k%16]-f[e[i].to][j];
  63. }
  64. t[e[i].v%16]--;
  65. g[e[i].to]+=tmp;
  66. f[e[i].to][e[i].v%16]++;
  67. for(int j=0;j<16;j++)
  68. {
  69. int k=j+e[i].v;
  70. g[e[i].to]+=k/16*t[j];
  71. f[e[i].to][k%16]+=t[j];
  72. }
  73. dfs2(e[i].to,x);
  74. }
  75. }
  76. int main()
  77. {
  78. bin[0]=1;
  79. for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;
  80. n=read(),m=read();
  81. for(int i=1;i<n;i++)
  82. {
  83. int u=read(),v=read(),w=read();
  84. insert(u,v,w);
  85. }
  86. dfs1(1,0);
  87. dfs2(1,0);
  88. for(int i=1;i<=n;i++)
  89. {
  90. ll ans=g[i]*16;
  91. for(int j=0;j<16;j++)ans+=(j^m)*f[i][j];
  92. printf("%I64d\n",ans);
  93. }
  94. return 0;
  95. }
  1. //不知道咋WA的树剖
  2. #include <iostream>
  3. #include <cstdio>
  4. using namespace std;
  5. #define LL long long
  6. const int N = 1e5 + 10;
  7. const int oo = 2e9;
  8. #define gc getchar()
  9. int n, m;
  10. LL f[105][105];
  11. inline int read() {
  12. int x = 0; char c = gc;
  13. while(c < '0' || c > '9') c = gc;
  14. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
  15. return x;
  16. }
  17. void Work_1() {
  18. for(int i = 1; i <= n; i ++)
  19. for(int j = 1; j <= n; j ++)
  20. f[i][j] = oo;
  21. for(int i = 1; i <= n; i ++)
  22. f[i][i] = 0;
  23. for(int i = 1; i < n; i ++) {
  24. int a = read(), b = read(), c = read();
  25. f[a][b] = f[b][a] = c;
  26. }
  27. for(int k = 1; k <= n; k ++)
  28. for(int i = 1; i <= n; i ++)
  29. for(int j = 1; j <= n; j ++)
  30. f[i][j] = min(f[i][k] + f[k][j], f[i][j]);
  31. /*for(int i = 1; i <= n; i ++) {
  32. for(int j = 1; j <= n; j ++)
  33. cout << f[i][j] << " ";
  34. cout << endl;
  35. }*/
  36. LL Answer(0);
  37. for(int i = 1; i <= n; i ++) {
  38. Answer = 0;
  39. for(int j = 1; j <= n; j ++) {
  40. Answer += (f[i][j] ^ m);
  41. }
  42. cout << Answer << endl;
  43. }
  44. }
  45. struct Node {int u, v, w, nxt;} G[4010];
  46. int head[N], topp[N], dis[N], fa[N], deep[N], size[N], son[N];
  47. int now = 1;
  48. inline void Add(int u, int v, int w) {
  49. G[now].v = v; G[now].w = w; G[now].nxt = head[u]; head[u] = now ++;
  50. }
  51. void Dfs_1(int u, int f_, int dep) {
  52. fa[u] = f_, deep[u] = dep;
  53. size[u] = 1;
  54. for(int i = head[u]; ~ i; i = G[i].nxt) {
  55. int v = G[i].v;
  56. if(v != f_) {
  57. dis[v] = dis[u] + G[i].w;
  58. Dfs_1(v, u, dep + 1);
  59. size[u] += size[v];
  60. if(size[v] > size[son[u]]) son[u] = v;
  61. }
  62. }
  63. }
  64. void Dfs_2(int u, int tp) {
  65. topp[u] = tp;
  66. if(!son[u]) return ;
  67. Dfs_2(son[u], tp);
  68. for(int i = head[u]; ~ i; i = G[i].nxt) {
  69. int v = G[i].v;
  70. if(v != fa[u] && v != son[u]) Dfs_2(v, v);
  71. }
  72. }
  73. inline int Lca(int x, int y) {
  74. int tp1 = topp[x], tp2 = topp[y];
  75. while(tp1 != tp2) {
  76. if(deep[tp1] < deep[tp2]) swap(x, y), swap(tp1, tp2);
  77. x = fa[tp1];
  78. tp1 = fa[x];
  79. }
  80. return deep[x] < deep[y] ? x : y;
  81. }
  82. void Work_2() {
  83. for(int i = 1; i <= n; i ++) head[i] = -1;
  84. for(int i = 1; i < n; i ++) {
  85. int u = read(), v = read(), w = read();
  86. Add(u, v, w); Add(v, u, w);
  87. }
  88. Dfs_1(1, 0, 1);
  89. Dfs_2(1, 1);
  90. for(int i = 1; i <= n; i ++) {
  91. LL Answer = 0;
  92. for(int j = 1; j <= n; j ++) {
  93. if(i == j) continue ;
  94. int lca = Lca(i, j);
  95. Answer += ((dis[i] + dis[j] - dis[lca] - dis[lca]) ^ m);
  96. }
  97. printf("%lld\n", Answer);
  98. }
  99. }
  100. int main() {
  101. freopen("warehouse.in", "r", stdin);
  102. freopen("warehouse.out", "w", stdout);
  103. n = read();
  104. m = read();
  105. if(n <= 100) Work_1();
  106. else if(n == 2000) Work_2();
  107. return 0;
  108. }

总结

暴力都不知道咋
,不擅长

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