6.17考试总结(NOIP模拟8)

背景

考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景。。。

T1星际旅行

前言

考试的时候用一个自己感觉非常妙的思路骗了20pts,因为是双向边,所以分成两个边存,边的tot从2开始,这样可以保证没一组边的序号通过取\(xor\)可以相互转化。

然后对于每一个边记录经过次数,并且记一下经过次数为1和2的边的总数,然后对于dfs时转移的就是状压的每组边的状态,当然也可以拿Hash存。

做法挺妙的,唯一的缺点就是和正解一点关系都没有(逃

解题思路

正解主要是欧拉路的相关知识。

首先可以确定的是,如果这个图里面的各个边不是联通的话(可以用冰茶几或者DFS来判),那么总情况数一定是0,比如下图的情况:

然后就是建立在欧拉路以及欧拉回路上面的东西了,

存在欧拉路的条件:图是连通的,有且只有2个奇点。

存在欧拉回路的条件:图是连通的,有0个奇点。

因此,问题就变成了把所有的边变成两条边之后,拆掉两条边使得新图仍然具有联通性,设自环数为\(cnt\),每个点的出入度为\(du[i]\),主要分为一下三种情况:

  • 去掉任意2个自环:情况数为\(\dfrac{cnt\times(cnt-1)}{2}\)
  • 去掉一个自环和一条边:情况数为:\(\dfrac{cnt \times \sum\limits_{i=1}^ndu_i}{2}\)
  • 去掉两个有公共点的边:情况数为\(\dfrac{\sum\limits_{i=1}^n du_i \times (du_i-1)}{2}\)

记得开long long

code

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=1e5+10,M=N<<1;
  5. int n,m,link=N-1,sum,sum1,sum2,sum3,du[N],rdu[N],fa[N];
  6. int find(int x)
  7. {
  8. if(fa[x]==x)
  9. return x;
  10. return fa[x]=find(fa[x]);
  11. }
  12. #undef int
  13. int main()
  14. {
  15. #define int register long long
  16. #define ll long long
  17. scanf("%lld%lld",&n,&m);
  18. for(int i=1;i<=n;i++)
  19. fa[i]=i;
  20. for(int i=1,x,y;i<=m;i++)
  21. {
  22. scanf("%lld%lld",&x,&y);
  23. if(x==y)
  24. {
  25. sum++;
  26. rdu[x]++;
  27. rdu[y]++;
  28. continue;
  29. }
  30. du[x]++;
  31. du[y]++;
  32. rdu[x]++;
  33. rdu[y]++;
  34. x=find(x);
  35. y=find(y);
  36. fa[x]=y;
  37. }
  38. for(int i=1;i<=n;i++)
  39. if(rdu[i])
  40. {
  41. link=i;
  42. find(i);
  43. break;
  44. }
  45. for(int i=1;i<=n;i++)
  46. if(rdu[i]&&find(i)!=fa[link])
  47. {
  48. printf("0");
  49. return 0;
  50. }
  51. sum1=sum*(sum-1)/2;
  52. for(int i=1;i<=n;i++)
  53. {
  54. sum2+=du[i];
  55. sum3+=du[i]*(du[i]-1)/2;
  56. }
  57. sum2=sum2*sum/2;
  58. printf("%lld",sum1+sum2+sum3);
  59. return 0;
  60. }

T2 砍树

前言

考试的时候想到了二分答案,以为自己要切题了,然后考试结束前20分钟的时候突然就搞出来一个反例,不满足单调性,但是时间又不够了,我就草草的在错误答案的基础上改了一下,骗了20pts

解题思路

首先说一下为什么不满足单调性,显然的天数与希望树木的高度是有倍数关系的。。

问题就是让我们求一个最大的\(d\),满足:

\[\sum\limits_{i=1}^n(\lceil \dfrac{a_i}{d}\rceil \times d-a_i)\le k
\]

移一下项,令\(T=k+\sum\limits_{i=1}^na_i\),可得:

\[\sum\limits_{i=1}^n\lceil \dfrac{a_i}{d}\rceil \times d\le T
\]
\[\sum\limits_{i=1}^n\lceil \dfrac{a_i}{d}\rceil \le \dfrac{T}{d}
\]
\[\sum\limits_{i=1}^n\lceil \dfrac{a_i}{d}\rceil \le \lfloor \dfrac{T}{d} \rfloor
\]

然后我们就可以愉快的整除分块,暴力枚举每一个d然后判断是否符合条件就好了,显然的,对于每一个块里,右端点是最优解。

code

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=110;
  5. int n,m,ans,temp,s[N];
  6. #undef int
  7. int main()
  8. {
  9. #define int register long long
  10. #define ll long long
  11. scanf("%lld%lld",&n,&m);
  12. for(int i=1;i<=n;i++)
  13. scanf("%lld",&s[i]);
  14. for(int i=1;i<=n;i++)
  15. temp+=s[i];
  16. temp+=m;
  17. for(int l=1,r;l<=temp;l=r+1)
  18. {
  19. r=temp/(temp/l);
  20. int sum=0;
  21. for(int i=1;i<=n;i++)
  22. sum+=ceil(1.0*s[i]/(1.0*r));
  23. if(sum<=temp/r)
  24. ans=r;
  25. }
  26. printf("%lld",ans);
  27. return 0;
  28. }

T3 超级树

前言

挺难的一道题,我考场上几乎是直接输出的样例,5pts,不知道是根据dp方程出的题还是出题人真的太强了,想出来的。。。

解题思路

首先要明白dp数组的含义:

dp[i][j]表示一棵i-超级树,有j条点不重复的路径的方案数

何为j条点不重复的路径?

在j条路径中,各个路径没有相交的部分(相同的点)。

考虑从dp[i]转移到dp[i+1],有五种转移状态

  • 什么也不做:\(dp[i+1][l+r]+=num\)

  • 根自己作为一条新路径 \(dp[i+1][l+r+1]+=num\)

  • 根连接到左子树(或右子树)的某条路径上 \(dp[i+1][l+r]+=2 \times num \times (l+r)\)

  • 根连接左子树和右子树的各一条路径 \(dp[i+1][l+r-1]+=2 \times num \times l\times r\)

  • 根连接左子树(或右子树)的两条路径 \(dp[i+1][l+r-1]+=num \times (l \times (l-1)+r \times (r-1))\)

边界为dp[1][0]=dp[1][1]=1,答案为dp[k][1]。

看起来第二维状态可能有\(2^k\)那么大,但注意到从dp[i]转移到dp[i+1]时,路径的条数最多减少1条,因此第二维只有k个状态对最终的状态有影响,只dp这些状态即可。

  • 注意:取\(\bmod\)运算不要太多,否则会TLE

code

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=610;
  5. int n,mod,f[N][N];
  6. #undef int
  7. int main()
  8. {
  9. #define int register long long
  10. #define ll long long
  11. scanf("%lld%lld",&n,&mod);
  12. f[1][0]=f[1][1]=1;
  13. for(int dep=1;dep<n;dep++)
  14. for(int i=0;i<=n;i++)
  15. for(int j=0;j<=n-i;j++)
  16. {
  17. int num=f[dep][i]*f[dep][j]%mod;
  18. f[dep+1][i+j]=(f[dep+1][i+j]+num)%mod;
  19. f[dep+1][i+j+1]=(f[dep+1][i+j+1]+num)%mod;
  20. f[dep+1][i+j]=(f[dep+1][i+j]+2*num*(i+j))%mod;
  21. f[dep+1][i+j-1]=(f[dep+1][i+j-1]+2*num*i*j)%mod;
  22. f[dep+1][i+j-1]=(f[dep+1][i+j-1]+num*(i*(i-1)+j*(j-1)))%mod;
  23. }
  24. printf("%lld",f[n][1]%mod);
  25. return 0;
  26. }

P4427 [BJOI2018]求和

前言

就这板子题,我竟然没有赛场上切掉,还是太菜了。。

解题思路

比较简单,先处理一下各种k次方,在搞一下深度的前缀和,剩下的就是LCA了(倍增,Tarjan,树链剖分都可以),当然也可以直接暴力向上跳,至于为什么又快又对,就非常玄学了。。。

  • 注意:取\(\bmod\)要到位

code

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=3e5+10,M=N<<1,mod=998244353;
  5. int n,Q,dep[N],f[N][25],q[51][N],po[N][51];
  6. int tot,head[N],nxt[M],ver[M];
  7. void add_edge(int x,int y)
  8. {
  9. ver[++tot]=y;
  10. nxt[tot]=head[x];
  11. head[x]=tot;
  12. }
  13. int ksm(int x,int y)
  14. {
  15. int temp=1;
  16. while(y)
  17. {
  18. if(y&1)
  19. temp=temp*x%mod;
  20. y>>=1;
  21. x=x*x%mod;
  22. }
  23. return temp;
  24. }
  25. void dfs(int x,int fa)
  26. {
  27. for(int i=head[x];i;i=nxt[i])
  28. {
  29. int to=ver[i];
  30. if(to==fa)
  31. continue;
  32. dep[to]=dep[x]+1;
  33. f[to][0]=x;
  34. dfs(to,x);
  35. }
  36. }
  37. void LCA_init()
  38. {
  39. dfs(1,0);
  40. for(int j=1;j<=20;j++)
  41. for(int i=1;i<=n;i++)
  42. f[i][j]=f[f[i][j-1]][j-1];
  43. }
  44. int LCA_ask(int x,int y)
  45. {
  46. if(x==y)
  47. return x;
  48. if(dep[x]>dep[y])
  49. swap(x,y);
  50. for(int i=20;i>=0;i--)
  51. if(dep[x]<=dep[f[y][i]])
  52. y=f[y][i];
  53. if(x==y)
  54. return x;
  55. for(int i=20;i>=0;i--)
  56. if(f[x][i]!=f[y][i])
  57. {
  58. x=f[x][i];
  59. y=f[y][i];
  60. }
  61. return f[x][0];
  62. }
  63. #undef int
  64. int main()
  65. {
  66. #define int register long long
  67. #define ll long long
  68. scanf("%lld",&n);
  69. for(int i=1,x,y;i<n;i++)
  70. {
  71. scanf("%lld%lld",&x,&y);
  72. add_edge(x,y);
  73. add_edge(y,x);
  74. }
  75. LCA_init();
  76. for(int i=1;i<=n;i++)
  77. {
  78. po[i][0]=1;
  79. for(int j=1;j<=50;j++)
  80. po[i][j]=po[i][j-1]*i%mod;
  81. }
  82. for(int i=0;i<=50;i++)
  83. for(int j=1;j<=n;j++)
  84. q[i][j]=(q[i][j-1]+po[j][i])%mod;
  85. scanf("%lld",&Q);
  86. while(Q--)
  87. {
  88. int x,y,k,lca;
  89. scanf("%lld%lld%lld",&x,&y,&k);
  90. lca=LCA_ask(x,y);
  91. printf("%lld\n",(((q[k][dep[x]]+q[k][dep[y]])%mod-q[k][dep[lca]]+mod)%mod-q[k][dep[f[lca][0]]]+mod)%mod);
  92. }
  93. return 0;
  94. }

6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]的更多相关文章

  1. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  2. 2021.6.17考试总结[NOIP模拟8]

    T1 星际旅行 其实就是求两条只走一遍的边的方案数. 考场上第一眼就感觉不可做,后来画了几个图,发现好像只要两个边是相连的就可以只走一遍,居然还真拿了30.. 其实是一道欧拉路的题,把每条非自环的边看 ...

  3. noip模拟8[星际旅行·砍树·超级树·求和]

    也不能算考得好,虽然这次A了一道题,但主要是那道题太简单了,没啥成就感,而且有好多人都A掉了 除了那一道,其他的加起来一共拿了25pts,这我能咋办,无奈的去改题 整场考试的状态并不是很好啊,不知道是 ...

  4. 5.23考试总结(NOIP模拟2)

    5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...

  5. 5.22考试总结(NOIP模拟1)

    5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...

  6. [考试总结]noip模拟23

    因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...

  7. 7.18 NOIP模拟测试5 星际旅行+砍树+超级树

    T1 星际旅行 题意:n个点,m条边,无重边,有自环,要求经过m-2条边两次,2条边一次,问共有多少种本质不同的方案.本质不同:当且仅当至少存在一条边经过次数不同. 题解:考试的时候理解错题,以为他是 ...

  8. 「考试」noip模拟9,11,13

    9.1 辣鸡 可以把答案分成 每个矩形内部连线 和 矩形之间的连线 两部分 前半部分即为\(2(w-1)(h-1)\),后半部分可以模拟求(就是讨论四种相邻的情况) 如果\(n^2\)选择暴力模拟是有 ...

  9. NOIP模拟测试5「星际旅行·砍树·超级树」

    星际旅行 0分 瞬间爆炸. 考试的时候觉得这个题怎么这么难, 打个dp,可以被儿子贡献,可以被父亲贡献,还有自环,叶子节点连边可以贡献,非叶子也可以贡献,自环可以跑一回,自环可以跑两回, 关键是同一子 ...

随机推荐

  1. What are CBR, VBV and CPB?

    转自:https://codesequoia.wordpress.com/2010/04/19/what-are-cbr-vbv-and-cpb/ It's common mistake to to ...

  2. [BUAA2021软工]结对第一阶段博客作业小结

    作业链接 结对项目-第一阶段 优秀作业推荐 本次博客作业虽然是简单总结,但是以下作业中都不乏有思考.有亮点的精彩内容,推荐给同学们阅读学习. 山鸣谷应,相得益彰--杰对项目-第一阶段总结 该组对于可能 ...

  3. 剑指offer 数组中的重复数字

    问题描述: 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1 ...

  4. (五)Jira Api对接:修改任务状态

    项目迭代结束后我们需要把sprint下面的story.task任务状态修改到结束状态,如果手动修改会花费不少时间,本文就介绍如何通过jira api自动修改任务状态,提高工作效率. 一.查看任务工作流 ...

  5. Aliyun SSL 证书签发&安装

    目录 HTTPS SSL证书 签发 和 应用 证书购买 证书申请 证书安装 参考文档 HTTPS SSL证书 签发 和 应用 - SSL证书服务(Alibaba Cloud SSL Certifica ...

  6. 还可以使用 -c 参数来显示全部内容,并标出不同之处 diff -c test2.txt test1.txt

    二.实例 在test目录下存放了两个文本文件,test1.txt  test2.txt . 比较这两个文件的异同. diff  test1.txt   test2.txt     "5c5& ...

  7. rpm命令的简介-(转自jb51.net )

    在Linux操作系统中,有一个系统软件包,它的功能类似于Windows里面的"添加/删除程序",但是功能又比"添加/删除程序"强很多,它就是Red Hat Pa ...

  8. Linux中级之netfilter/iptables应用及补充

    一.iptables介绍 Netfilter/Iptables(以下简称Iptables)是unix/linux自带的一款优秀且开放源代码的完全自由的基于包过滤的防火墙工具,它的功能十分强大,使用非常 ...

  9. JavaEE 学大数据是否掌握 JavaSE 和 Linux 就够了?

    引言 如果你是学习大数据的童靴,可能经常在网上看到一些公众号或博客告诉你,学习大数据基础部分只需要掌握 JavaSE 和 Linux 就够了,至于 JavaWeb 和 JavaEE 简单了解一下就可以 ...

  10. K8s之二进制安装高可用集群

    1.环境准备 #二进制部署安装文档# https://github.com/easzlab/kubeasz/blob/master/docs/setup/00-planning_and_overall ...