10.24考试题解qwq
考点难度都很合适的一套题目,大概在day1到day2之前
T1
猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有N个苹果,每个苹果有一个编号,分
别为0~N-1,它们之间由N-1个树枝相连,猴猴可以从树枝的一端爬到树枝的另一端,所以猴猴可
以从任意一个苹果的位置出发爬到任意猴猴想去的苹果的位置。猴猴开始在编号为K的苹果的位
置,并且把这个苹果吃了,之后每一天猴猴都要去吃一个苹果,但是树上那么多苹果吃哪个呢?
猴猴想到自己去吃苹果时一定会把路上遇到的苹果都吃掉,于是猴猴决定去吃能让自己这天吃的
苹果数量最多的那个苹果,如果有多个苹果满足条件,猴猴就会去吃这些中编号最小的苹果,那
么猴猴会按照什么顺序吃苹果呢?
对于30%的数据:N<=100
对于60%的数据:N<=1000
对于100%的数据:N<=50000,0<=K<N
分析:60%的分数都只要暴力模拟就好了,每次找最长的走过去;
考虑一个性质:走过的点的权值会消失,那么每次移动到终点位置和每次都从初始给定的点出发的答案都一样的,而且终点一定会是叶子节点;
那么我们设初始节点为根节点,先进行一遍dfs,把所有叶子节点记录下来,按照深度排序;
然后让每个点沿着父亲往上跳,每跳一步答案增加1,遇到根节点或者走过的节点就停止(遇到走过的点说明上面的权值都没有了
然后把叶子节点按答案从小到大输出(看完题解觉得智商被人按在地上摩擦了)
#include<bits/stdc++.h>
using namespace std;
namespace knife_rose{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=;char ch,f=;
for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
if(ch=='-') f=,ch=getchar();
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
}
const int N=1e5+;
int n,rt;
int head[N],cnt;
struct point
{
int nxt,to;
point(){}
point(const int &nxt,const int &to):nxt(nxt),to(to){}
}a[N<<];
inline void link(int x,int y)
{
a[++cnt]=(point){head[x],y};head[x]=cnt;
a[++cnt]=(point){head[y],x};head[y]=cnt;
}
int f[N],dep[N],lea[N],num,sum[N];
bool vis[N];
inline void dfs(int now,int fa)
{
f[now]=fa;
dep[now]=dep[fa]+;
bool flag=;
for(int i=head[now];i;i=a[i].nxt)
{
int t=a[i].to;
if(t==fa) continue;
flag=;
dfs(t,now);
}
if(!flag) lea[++num]=now;
}
inline bool cmp1(int a,int b)//深度排序,深度相同按编号大小
{
return dep[a]^dep[b]?dep[a]>dep[b]:a<b;
}
inline bool cmp2(int a,int b)//答案排序
{
return sum[a]^sum[b]?sum[a]>sum[b]:a<b;
}
signed main()
{
n=read(),rt=read();
for(int x,i=;i<n;++i)
{
x=read();
link(x,i);
}
dfs(rt,rt);
sort(lea+,lea+num+,cmp1);
vis[rt]=;
for(int i=;i<=num;++i)
{
int now=lea[i];
while(!vis[now])
{
++sum[lea[i]];
vis[now]=;
now=f[now];
}
}
sort(lea+,lea+num+,cmp2);
printf("%d\n",rt);
for(int i=;i<=num;++i) printf("%d\n",lea[i]);
return ;
}
}
signed main()
{
return knife_rose::main();
}
T2
猴猴最爱吃香蕉了。每天猴猴出门都会摘很多很多的香蕉,每个香蕉都有一个甜度,猴猴不一定
要把所有的香蕉都吃掉,猴猴每天都有一个心情值K,猴猴希望当天吃的香蕉满足这么一个条件,
这些香蕉的甜度乘积恰好等于K,但是猴猴并不知道有多少种方法,于是猴猴把这个问题交给你。
对于30%的数据:n,K<=100
对于60%的数据:n<=1000,K<=10000
对于100%的数据:n<=1000,K<=100000000,D<=20(D是数据组数
30%:我也没想出来咋拿30分(
60%:题目是个很明显的背包,但是由于是乘法所以有一些特殊之处:只有k的约数才能作为转移,所以我们可以筛出来k的约数,是根号量级的;
统计答案需要二分查找,复杂度O(D×n√k×log(√k))
100%:其实上面那个做法就是100分,然而官方题解也是这么给的,但是很明显复杂度不对啊qwq
然而机房里某位巨佬想出了复杂度更优秀的做法,%%%szx
先对k进行质因数分解,根据每个质因子个数将答案压缩成一个多进制状态,然后将每个a[i]也压缩成对应的多进制状态进行转移,可以发现质因子个数很少,不超过30个
设t是多进制状态最大值
复杂度为O(√k+n√a[i]+nt)
#include<bits/stdc++.h>
using namespace std;
namespace knife_rose{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=;char ch,f=;
for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
if(ch=='-') f=,ch=getchar();
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
}
const int N=1e4+,p=1e9+;
int tyx,n,m,ed,tot;
int a[N];
int st[],sum[],top;
int git[],c[],s[N][];
int g[N],f[];
bool vis[N];
inline void clear()
{
memset(g,,sizeof(g));
memset(f,,sizeof(f));
memset(sum,,sizeof(sum));
memset(s,,sizeof(s));
memset(vis,,sizeof(vis));
top=;
}
signed main()
{
tyx=read();
while(tyx--)
{
clear();
n=read(),m=read();
for(int i=;i<=n;++i) a[i]=read();
int qr=sqrt(m),tmp=m;
for(int i=;i<=qr;++i)
{
if(tmp%i==)
{
st[++top]=i;
while(tmp%i==) ++sum[top],tmp/=i;//质因数分解
}
}
if(tmp^) st[++top]=tmp,sum[top]=;//加上大质因子
git[]=;
for(int i=;i<=top;++i)
git[i+]=git[i]*(sum[i]+);//git[i]表示,多进制状态下,第i位一个1代表十进制多少
ed=;
for(int i=;i<=top;++i) ed+=git[i]*sum[i];//ed是最终状态
for(int i=;i<=n;++i)
{
if(m%a[i]){vis[i]=;continue;}//不是M的约数没用
qr=sqrt(a[i]),tot=;
for(int j=;j<=qr;++j)
{
if(a[i]%j==)
{
c[++tot]=j;
while(a[i]%j==) ++s[i][tot],a[i]/=j;//质因数分解*2
}
}
if(a[i]^) c[++tot]=a[i],s[i][tot]=;
int t=;
for(int j=;j<=top;++j)
{
while(c[t]<st[j]&&t<tot) ++t;
if(c[t]==st[j]) g[i]+=git[j]*s[i][t];//g[i]为a[i]对应的多进制状态数
}
}
f[]=;
for(int t,now,flag,i=;i<=n;++i)
{
if(vis[i]) continue;
for(int j=ed;~j;--j)
{
flag=;
t=;
for(int k=;k<=top;++k)
{
now=(j%git[k+])/git[k];//now是a[i]对应的g[i]在第i位有多大
if(now+(g[i]%git[k+])/git[k]>sum[k]){flag=;break;}//如果第i位当前数字+g[i]的第i位数字大于上界取消
t+=(now+(g[i]%git[k+])/git[k])*git[k];
}
if(flag) continue;
f[t]+=f[j];
if(f[t]>=p) f[t]-=p;
}
}
printf("%d\n",f[ed]);
}
return ;
}
}
signed main()
{
return knife_rose::main();
}
/*
1
10 10
1 5 1 2 4 5 1 2 1 5 */
T3
猴猴今天要和小伙伴猩猩比赛爬树,为了公平不碰撞,猴猴和猩猩需要在不同的树上攀爬。于是
它们选了两颗节点数同为n的树,并将两棵树的节点分别以1~n标号(根节点标号为1),但两棵树
的节点连接方式不尽相同。
现在它们决定选择两个标号的点进行比赛。为了方便统计,规定它们比赛中必须都向上爬。(即
选定的赛段节点u→节点v都必须指向叶子方向)请你求出这两棵树上共有多少对节点满足比赛的需
求。
对于30%的数据:n≤1000
对于50%的数据:n≤10000
对于100%的数据:n≤100000,1≤a,b≤n
题意大概是选一对点使得在这两颗树上都满足某个点是另一个点的祖先
30%:记录每个点是不是在两棵树上都是自己祖先,枚举点对
50%:???好像没啥办法
100%:其实这个题目就是一个树上逆序对问题,我们考虑先对第一颗树以dfs序为下标建树状数组,再遍历第二棵树,每次进去的先把自己放进树状数组,然后求一下当前子树范围内点的个数,出来的时候再求一遍,两次结果作差就是满足题目要求的点对(进去的时候不存在而回溯的时候存在说明既是第一颗树的子树也是第二棵树的子树)
#include<bits/stdc++.h>
using namespace std;
namespace knife_rose{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=;char ch,f=;
for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
if(ch=='-') f=,ch=getchar();
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
}
const int N=1e5+;
int n,ret;
int head[N],cnt;
struct point
{
int nxt,to;
point(){}
point(const int &nxt,const int &to):nxt(nxt),to(to){}
}a[N<<];
inline void link(int x,int y)
{
a[++cnt]=(point){head[x],y};head[x]=cnt;
a[++cnt]=(point){head[y],x};head[y]=cnt;
}
int st[N],ed[N],idx;
inline void dfs1(int now,int fa)
{
st[now]=++idx;
for(int i=head[now];i;i=a[i].nxt)
{
int t=a[i].to;
if(t==fa) continue;
dfs1(t,now);
}
ed[now]=idx;
}
int tr[N];
inline int lowbit(int i)
{
return i&-i;
}
inline void update(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
tr[i]+=k;
}
inline int query(int y)
{
int ret=;
for(int i=y;i;i^=lowbit(i))
ret+=tr[i];
return ret;
}
inline void dfs2(int now,int fa)//树上逆序对
{
int ans=query(ed[now])-query(st[now]-);
for(int i=head[now];i;i=a[i].nxt)
{
int t=a[i].to;
if(t==fa) continue;
dfs2(t,now);
}
ret+=query(ed[now])-query(st[now]-)-ans;
update(st[now],);
}
signed main()
{
n=read();
for(int x,y,i=;i<n;++i)
{
x=read(),y=read();
link(x,y);
}
dfs1(,);
memset(head,,sizeof(head));
cnt=;
for(int x,y,i=;i<n;++i)
{
x=read(),y=read();
link(x,y);
}
dfs2(,);
printf("%d\n",ret);
return ;
}
}
signed main()
{
return knife_rose::main();
}
10.24考试题解qwq的更多相关文章
- 题解 2020.10.24 考试 T2 选数
题目传送门 题目大意 见题面. 思路 本来以为zcx.pxj变强了,后来发现是SPJ出问题了...考试的时候感觉有点人均啊...结果自己还是只想出来一半. 我们假设 \(f(x)=(\lfloor\f ...
- 题解 2020.10.24 考试 T4 模板
题目传送门 题目大意 有一个 \(n\) 个点组成的树,有 \(m\) 次操作,每次将 \(1\to x\) 的路径上每个点都加入一个颜色为 \(c\) 的小球.但是每个点都有大小限制,即小球个数超过 ...
- 题解 2020.10.24 考试 T3 数列
题目传送门 题目大意 给出一个数 \(n\),你要构造一个数列,满足里面每个数都是 \(n\) 的因子,且每一个数与前面不互质的个数不超过 \(1\).问有多少种合法方案. 保证 \(n\) 的不同质 ...
- 10.24 正睿停课训练 Day8 AM
目录 2018.10.24 正睿停课训练 Day8 AM A 棒棒糖(组合) B 彩虹糖(思路 博弈) C 泡泡糖(DP) 考试代码 A B C 2018.10.24 正睿停课训练 Day8 AM 期 ...
- 2016 10 28考试 dp 乱搞 树状数组
2016 10 28 考试 时间 7:50 AM to 11:15 AM 下载链接: 试题 考试包 这次考试对自己的表现非常不满意!! T1看出来是dp题目,但是在考试过程中并没有推出转移方程,考虑了 ...
- 背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令
[源码下载] 背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令 作者:webabcd ...
- Leetcode 10. 正则表达式匹配 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
- python中使用Opencv进行车牌号检测——2018.10.24
初学Python.Opencv,想用它做个实例解决车牌号检测. 车牌号检测需要分为四个部分:1.车辆图像获取.2.车牌定位.3.车牌字符分割和4.车牌字符识别 在百度查到了车牌识别部分车牌定位和车牌字 ...
- table-cell http://www.cnblogs.com/StormSpirit/archive/2012/10/24/2736453.html
http://www.cnblogs.com/StormSpirit/archive/2012/10/24/2736453.html
随机推荐
- kudu 查看元数据信息
package com.lala.lala.pipe.dbinfo import org.apache.kudu.client.KuduClient import com.lala.lala.comm ...
- 可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?
本文由原作者松若章原创发布,作者主页:zhihu.com/people/hrsonion/posts,感谢原作者的无私分享. 1.引言 一道经典的面试题是:从 URL 在浏览器被被输入到页面展现的过程 ...
- Vue.js 源码分析(二十四) 高级应用 自定义指令详解
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令. 官网介绍的比较抽象,显得很高大上,我个人对自定义指令的理解是:当自定义指令作用在一些DOM元素或组件上 ...
- maven项目配置使用jdk1.8进行编译的插件
在使用Maven插件编译Maven项目的时候报了这样一个错:[Java source1.5不支持diamond运算符,请使用source 7或更高版本以启用diamond运算符],这里记录下出现这个错 ...
- 异步IO/协程/数据库/队列/缓存(转)
原文:Python之路,Day9 - 异步IO\数据库\队列\缓存 作者:金角大王Alex add by zhj: 文章很长 引子 到目前为止,我们已经学了网络并发编程的2个套路, 多进程,多线程,这 ...
- 用guava快速打造两级缓存能力
首先,咱们都有一共识,即可以使用缓存来提升系统的访问速度! 现如今,分布式缓存这么强大,所以,大部分时候,我们可能都不会去关注本地缓存了! 而在一起高并发的场景,如果我们一味使用nosql式的缓存,如 ...
- WPF控件模板(6)
什么是ControlTemplate? ControlTemplate(控件模板)不仅是用于来定义控件的外观.样式, 还可通过控件模板的触发器(ControlTemplate.Triggers)修改控 ...
- Java自学-集合框架 Collections
Java集合框架 工具类Collections Collections是一个类,容器的工具类,就如同Arrays是数组的工具类 步骤 1 : 反转 reverse 使List中的数据发生翻转 pack ...
- codeforces #579(div3)
codeforces #579(div3) A. Circle of Students 题意: 给定一个n个学生的编号,学生编号1~n,如果他们能够在不改变顺序的情况下按编号(无论是正序还是逆序,但不 ...
- 基础系列(2)--- css1
css组成 css语法组成 选择器 和 声明 (多个声明用分号隔开) 声明包括 属性和属性值(多个属性值用空格隔开) 语法: 选择器{ 属性: 属性值; 属性: 属性值1 属性值2; } css样式表 ...