noip8
T1
星际旅行
考试时觉得是道数学题,但没想到忘了欧拉路。
首先将每条边都拆成两条边,那么题目就变成了任意删掉两条边,使得新的图中存在欧拉路。设 \(sum\) 表示自环的数量, \(du_{i}\) 表示不算自环,点 \(i\) 的度数,考虑以下几种情况,
删任意两个自环,则对答案的贡献为 \(\frac{sum\times\left(sum-1\right)}{2}\)
删一个自环和任意一条边,则对答案的贡献为 \(sum\times(m-sum)\)
删两条有公共顶点的边,因为删完边后,图中点的度数都为偶数,所以删的边肯定是要有一个公共顶点的,则对答案的贡献为 \(\sum_{i=1}^{n}\frac{du_{i}\times\left(du_{i}-1\right)}{2}\)
注意判断图是否连通。
Code
#include<cstdio>
#define MAX 100001
#define re register
#define int long long
namespace OMA
{
int n,m;
struct Graph
{
int next;
int to;
}edge[MAX<<1];
int cnt=1,head[MAX];
int ans,sum,du[MAX];
int vis[MAX],link[MAX];
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
inline void add(int u,int v)
{
edge[++cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt;
}
inline void dfs(int u)
{
vis[u] = 1;
for(re int i=head[u]; i; i=edge[i].next)
{
int v = edge[i].to;
if(!vis[v])
{ dfs(v); }
}
}
signed main()
{
n = read(),m = read();
for(re int i=1; i<=m; i++)
{
int u = read(),v = read();
if(u==v)
{ link[u] = 1,sum++; }
else
{
add(u,v),add(v,u);
du[u]++,du[v]++;
}
}
for(re int i=1; i<=n; i++)
{
if(link[i]||du[i])
{ dfs(i); break; }
}
for(re int i=1; i<=n; i++)
{
if(!vis[i]&&(link[i]||du[i]))
{ printf("0\n"); return 0; }
}
ans = sum*(m-sum)+sum*(sum-1)/2;
for(re int i=1; i<=n; i++)
{ ans += du[i]*(du[i]-1)/2; }
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }
T2
考试时想的是二分,但二分并不正确,因为并不满足单调性好像是屁话。
首先我们能得出一个式子,
\]
移项可得,
\]
设右侧的一大堆为 \(temp\) ,然后我们枚举 \(d\) ,用分块的思想,显然,对于每一个 \(temp\) 相等的区间中,右端点是最优的,然后判断是否合法,然后转移答案。
Code
#include<cmath>
#include<cstdio>
#include<algorithm>
#define MAX 101
#define re register
#define int long long
namespace OMA
{
int a[MAX];
int n,k,ans;
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
signed main()
{
n = read(),k = read();
for(re int i=1; i<=n; i++)
{ k += a[i] = read(); }
for(re int l=1,r; l<=k; l=r+1)
{
r = k/(k/l);
int temp = 0;
for(re int i=1; i<=n; i++)
{ temp += (int)ceil((double)a[i]/r); }
if(temp<=k/r)
{ ans = r; }
}
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }
T3
一开始以为是个数学题,开始打表找规律,无果,想了想,觉得是个 \(dp\) 然而我状态转移方程啥也推不出来。输出0骗了5pts
正解是个 \(dp\) ,设 \(dp_{i,j}\) 表示是 \(i\)-超级树,有 \(j\) 条点不重复的路径的方案数。
考虑\(dp_{i}\) 对 \(dp_{i+1}\) 的贡献,枚举左子树的路径数 \(l\) ,右子树的路径数 \(r\) ,设 \(temp=dp_{i,l}\times dp_{i,r}\) ,有以下几种情况,
- 啥也不干, \(dp\left(i+1,l+r\right)+=temp\)
- 根自己作为一条新路径, \(dp\left(i+1,l+r+1\right)+=temp\)
- 根连接到左子树或右子树的一条路径上, \(dp\left(i+1,l+r\right)+=2\times temp\times \left(l+r\right)\)
- 根连接左子树和右子树的一条路径, \(dp\left(i+1,l+r-1\right)+=2\times temp\times l\times r\)
- 根连接左子树或右子树的两条路径, \(dp\left(i+1,l+r-1\right)+=temp\times\left(l\times\left(l-1\right)+r\times\left(r-1\right)\right)\)
然后直接转移即可。
Code
#include<cstdio>
#define MAX 301
#define re register
#define int long long
namespace OMA
{
int k,mod;
int dp[MAX][MAX];
signed main()
{
scanf("%lld%lld",&k,&mod);
dp[1][0] = dp[1][1] = 1;
for(re int i=0; i<=k-1; i++)
{
for(re int l=0; l<=k; l++)
{
for(re int r=0; r<=k; r++)
{
int temp = dp[i][l]*dp[i][r]%mod;
if(l+r<=k)
{
dp[i+1][l+r] += temp;
dp[i+1][l+r] += 2*temp*(l+r);
dp[i+1][l+r] %= mod;
}
if(l+r+1<=k)
{ (dp[i+1][l+r+1] += temp) %= mod; }
if(l+r-1<=k)
{
dp[i+1][l+r-1] += 2*temp*l*r;
dp[i+1][l+r-1] += temp*((l*(l-1))+r*(r-1));
dp[i+1][l+r-1] %= mod;
}
}
}
}
printf("%lld\n",dp[k][1]%mod);
return 0;
}
}
signed main()
{ return OMA::main(); }
T4
求和
本次考试最水的一道题,然而 \(LCA\) 打错了,直接爆0。
直接找询问的两个点的 \(LCA\) 然后从 \(LCA\) 开始分别向两个点枚举深度,并统计答案,记得最后再容斥一下,因为 \(LCA\) 的深度算了两遍。
然后这样过不掉luogu的加强数据,只需预处理一下前缀和即可。
以下为朴素算法
Code
#include<cstdio>
#define MAX 300001
#define re register
#define int long long
namespace OMA
{
int n,m;
struct Graph
{
int next;
int to;
}edge[MAX<<1];
int bin[MAX];
int cnt=1,head[MAX];
int anc[MAX][50],dep[MAX];
const int p = 998244353;
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
inline void add(int u,int v)
{
edge[++cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt;
}
void dfs(int u,int fa)
{
dep[u] = dep[anc[u][0] = fa]+1;
for(re int i=1; i<=bin[dep[u]]; i++)
{ anc[u][i] = anc[anc[u][i-1]][i-1]; }
for(re int i=head[u]; i; i=edge[i].next)
{
int v = edge[i].to;
if(v!=fa)
{ dfs(v,u); }
}
}
inline void swap(int &a,int &b)
{ int t=a; a=b; b=t; }
inline int LCA(int a,int b)
{
if(dep[a]<dep[b])
{ swap(a,b); }
while(dep[a]>dep[b])
{ a = anc[a][bin[dep[a]-dep[b]]]; }
if(a==b)
{ return a; }
for(re int i=bin[dep[a]]; ~i; i--)
{
if(anc[a][i]!=anc[b][i])
{ a = anc[a][i],b = anc[b][i]; }
}
return anc[a][0];
}
inline int quickpow(int a,int b)
{
int ans = 1;
while(b)
{
if(b&1)
{ ans = ans*a%p; }
a = a*a%p;
b >>= 1;
}
return ans;
}
signed main()
{
n = read();
for(re int i=2; i<=n; i++)
{
int u = read(),v = read();
add(u,v),add(v,u);
bin[i] = bin[i>>1]+1;
}
dfs(1,0);
m = read();
for(re int i=1; i<=m; i++)
{
int a = read(),b = read(),k = read();
int lca = LCA(a,b),ans = 0;
for(re int j=dep[lca]; j<=dep[a]; j++)
{ ans = (ans+quickpow(j-1,k))%p; }
for(re int j=dep[lca]; j<=dep[b]; j++)
{ ans = (ans+quickpow(j-1,k))%p; }
ans = (ans-quickpow(dep[lca]-1,k))%p;
printf("%lld\n",(ans%p+p)%p);
}
return 0;
}
}
signed main()
{ return OMA::main(); }
noip8的更多相关文章
- [考试总结]noip8
又是一个题的正解都没有打出来的一天 但是自己独创了 \(lca\) 的求法, 然而如果去掉求 \(lca\) 的过程,就不会 \(TLE\) 了. \(\huge{\text{囧}}\) 然后就是对性 ...
随机推荐
- 测试基础(四)Jmeter基础使用
前言 通过测试基础(三) Jmeter安装 - 大风北吹 - 博客园 (cnblogs.com)安装完成Jmeter后,就可以使用Jmeter进行性能测试. 一.线程组 (1).线程组分类 Jmete ...
- GKCTF X DASCTF 2021_babycat复现学习
17解的一道题,涉及到了java反序列化的知识,学习了. 看了下积分榜,如果做出来可能能进前20了哈哈哈,加油吧,这次就搞了两个misc签到,菜的扣脚. 打开后是个登录框,sign up提示不让注册, ...
- 机器学习Sklearn系列:(三)决策树
决策树 熵的定义 如果一个随机变量X的可能取值为X={x1,x2,..,xk},其概率分布为P(X=x)=pi(i=1,2,...,n),则随机变量X的熵定义为\(H(x) = -\sum{p(x)l ...
- Django基础006--在pycharm中将项目配置为Django项目
1.在File--Settings--搜索Django 操作按照如图所示 2.在pycharm右上方项目处,选择Edit Configurations 3.在Name处写上项目名称 python环境选 ...
- python 构造函数 析构函数
#构造函数是在对象被创建是自动调用的方法,用来完成初始化操作class Test(object): def __init__(self, name): self.name = name print(' ...
- Java基础00-内部类23
1. 内部类 内部类 1.1 内部类概述 代码示例: 1.2 成员内部类 代码示例: 创建一个成员内部类:定义时没有小括号是因为类是没有形参的.在类的成员位置,就是成员内部类了 创建测试类:这里发现不 ...
- vue(21)初识Vuex
Vuex是做什么的? 官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式. 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. Vuex ...
- python+API接口测试框架设计(unittest)
1.测试框架简介 整个接口测试框架的设计图如下: basepage:存放的是公共的方法 common:存放的是自定义工具 data:存放的是公共动态数据,如BB.xls/ Id.md log:存放的是 ...
- 【LeetCode】142. 环形链表 II
142. 环形链表 II 知识点:链表:set:快慢指针 题目描述 给定一个链表,判断链表中是否有环. 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表 ...
- 流畅的python--函数
# # -*- coding: utf-8 -*-#from abc import ABC ,abstractclassmethodfrom collections import namedtuple ...