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

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,M=N<<1;
int n,m,link=N-1,sum,sum1,sum2,sum3,du[N],rdu[N],fa[N];
int find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
#undef int
int main()
{
#define int register long long
#define ll long long
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1,x,y;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
if(x==y)
{
sum++;
rdu[x]++;
rdu[y]++;
continue;
}
du[x]++;
du[y]++;
rdu[x]++;
rdu[y]++;
x=find(x);
y=find(y);
fa[x]=y;
}
for(int i=1;i<=n;i++)
if(rdu[i])
{
link=i;
find(i);
break;
}
for(int i=1;i<=n;i++)
if(rdu[i]&&find(i)!=fa[link])
{
printf("0");
return 0;
}
sum1=sum*(sum-1)/2;
for(int i=1;i<=n;i++)
{
sum2+=du[i];
sum3+=du[i]*(du[i]-1)/2;
}
sum2=sum2*sum/2;
printf("%lld",sum1+sum2+sum3);
return 0;
}

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

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=110;
int n,m,ans,temp,s[N];
#undef int
int main()
{
#define int register long long
#define ll long long
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&s[i]);
for(int i=1;i<=n;i++)
temp+=s[i];
temp+=m;
for(int l=1,r;l<=temp;l=r+1)
{
r=temp/(temp/l);
int sum=0;
for(int i=1;i<=n;i++)
sum+=ceil(1.0*s[i]/(1.0*r));
if(sum<=temp/r)
ans=r;
}
printf("%lld",ans);
return 0;
}

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

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=610;
int n,mod,f[N][N];
#undef int
int main()
{
#define int register long long
#define ll long long
scanf("%lld%lld",&n,&mod);
f[1][0]=f[1][1]=1;
for(int dep=1;dep<n;dep++)
for(int i=0;i<=n;i++)
for(int j=0;j<=n-i;j++)
{
int num=f[dep][i]*f[dep][j]%mod;
f[dep+1][i+j]=(f[dep+1][i+j]+num)%mod;
f[dep+1][i+j+1]=(f[dep+1][i+j+1]+num)%mod;
f[dep+1][i+j]=(f[dep+1][i+j]+2*num*(i+j))%mod;
f[dep+1][i+j-1]=(f[dep+1][i+j-1]+2*num*i*j)%mod;
f[dep+1][i+j-1]=(f[dep+1][i+j-1]+num*(i*(i-1)+j*(j-1)))%mod;
}
printf("%lld",f[n][1]%mod);
return 0;
}

P4427 [BJOI2018]求和

前言

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

解题思路

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

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

code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10,M=N<<1,mod=998244353;
int n,Q,dep[N],f[N][25],q[51][N],po[N][51];
int tot,head[N],nxt[M],ver[M];
void add_edge(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
int ksm(int x,int y)
{
int temp=1;
while(y)
{
if(y&1)
temp=temp*x%mod;
y>>=1;
x=x*x%mod;
}
return temp;
}
void dfs(int x,int fa)
{
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i];
if(to==fa)
continue;
dep[to]=dep[x]+1;
f[to][0]=x;
dfs(to,x);
}
}
void LCA_init()
{
dfs(1,0);
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
}
int LCA_ask(int x,int y)
{
if(x==y)
return x;
if(dep[x]>dep[y])
swap(x,y);
for(int i=20;i>=0;i--)
if(dep[x]<=dep[f[y][i]])
y=f[y][i];
if(x==y)
return x;
for(int i=20;i>=0;i--)
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
return f[x][0];
}
#undef int
int main()
{
#define int register long long
#define ll long long
scanf("%lld",&n);
for(int i=1,x,y;i<n;i++)
{
scanf("%lld%lld",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
LCA_init();
for(int i=1;i<=n;i++)
{
po[i][0]=1;
for(int j=1;j<=50;j++)
po[i][j]=po[i][j-1]*i%mod;
}
for(int i=0;i<=50;i++)
for(int j=1;j<=n;j++)
q[i][j]=(q[i][j-1]+po[j][i])%mod;
scanf("%lld",&Q);
while(Q--)
{
int x,y,k,lca;
scanf("%lld%lld%lld",&x,&y,&k);
lca=LCA_ask(x,y);
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);
}
return 0;
}

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. 【实用小技巧】spring springmvc集成shiro时报 No bean named 'shiroFilter' available

    查了网上的,很多情况,不同的解决办法,总归一点就是配置文件加载的问题. 先看下配置文件中的配置 web.xml中的主要配置(这是修改后不在报错的:仅仅修改了一个位置:[classpath:spring ...

  2. vuex、localStorage、sessionStorage之间的区别

    vuex存储在内存中,localStorage以文件形式存储在本地,sessionStorage针对一个session(阶段)进行数据存储. 当页面刷新时vuex存储的数据会被清除,localStor ...

  3. 浅入浅出 MySQL 索引

    简单了解索引 首先,索引(Index)是什么?如果我直接告诉你索引是数据库管理系统中的一个有序的数据结构,你可能会有点懵逼. 为了避免这种情况,我打算举几个例子来帮助你更容易的认识索引. 我们查询字典 ...

  4. IP包头部格式解析

    IPv4首部一般是20字节长.在以太网帧中,IPv4包首部紧跟着以太网帧首部,同时以太网帧首部中的协议类型值设置为080016. IPv4提供不同,大部分是很少用的选项,使得IPv4包首部最长可扩展到 ...

  5. J2SE基础题

    J2SE基础 八种基本数据类型的大小,以及他们的封装类.(有的也说是9中基本数据类型,包括了void) 基本类型 大小(字节) 默认值 封装类 byte 1 (byte)0 Byte short 2 ...

  6. 事后分析$\beta$

    项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求 事后分析 我们在这个课程的目标是 提升团队管理及合作能力,开发一项满意的工程项目 这个作业在哪个具体方面帮助我们实现目标 组织组员 ...

  7. 使用 vue3 的自定义指令给 element-plus 的 el-dialog 增加拖拽功能

    element-plus 提供的 el-dialog 对话框功能非常强大,只是美中不足不能通过拖拽的方式改变位置,有点小遗憾,那么怎么办呢?我们可以通过 vue 的自定义指令来实现一个可以拖拽的对话框 ...

  8. [c++] 分号的使用

    加分号的情况: 语句结束加分号(否则编译器不知道在哪里结束语句,编译器不识别换行,写代码时换行和退格只是为了看着舒服,但本质上代码是写给编译器看的) 声明语句后加分号(也是一种语句) 结构体.类定义后 ...

  9. [刷题] 349 Intersection of Two Arrays

    查找问题 查找有无(只有键) 元素'a'是否存在 set(集合) 查找对应关系(键值对应) 元素'a'出现了几次 map(字典) set和map的底层实现是红黑树 常见操作 insert() find ...

  10. Vim安装记录

    Vim安装记录 参考链接 安装命令 1. 安装依赖库 2. 下载最新vim源码 3. 删除旧版vim 4. 配置configure.编译.安装 5. 设置vim为默认编辑器 6. 必要的配置 Vim安 ...