3、点点玩 deeeep(deeeep.cpp)

描述
  点点最近迷上了 deeeep(此 de 非彼 de),在研究一个特殊的
最长树链问题(树链即树上的一条路径)。现在一棵树中的每个点
都有一个 deeeep 值(正整数)
,点点想在树中找出最长的树链,使
得这条树链上所有对应点的 deeeep 值的最大公约数大于 1。请求出
这条树链的长度。(巨说这道题很 water!
)
格式
输入格式
第 1 行:整数 n(1 ≤ n ≤ 100000),表示点的个数。
第 2~n 行:每行两个整数 x,y 表示 x 和 y 之间有边,数据保证给
出的是一棵树。
第 n+1 行:n 个整数,依次表示点 1~n 对应的权值(1 ≤ 权值 ≤
1,000,000,000)

输出格式输出一个整数,表示这条树链的长度。
样例 1
样例输入 1
4
1 2
1 3
2 4
6 4 5 2
样例输出 1
3
限制
对于 100%的数据 1≤n≤100000,1≤ai≤10^9

Solution:

  本题考察搜索+数学。
    实际上就是乱写暴力。bfs爆搜能ac,还比正解快,简直鬼畜。
    枚举每个约数,保留对应的边,做一次最长路径。因为一个数的约数个数可以保证,所以复杂度符合要求。
    看起来10^9很虚,但是我们分解质因数只需要预处理出3*10^4里的质数,实际上只有3000多个,3000*n完全不虚,所以我们可以先将n个数全都分解质因数。
  然后我们枚举每个质数,枚举所有包含这些质数的点,看一下这些点在树上能形成的最长的链有多长。具体做法是我们将这些点按照深度从大到小排序,然后更新每个点父亲的子树中到父亲的最长链、次长链分别是多长,乱搞一下就行了。

代码:

bfs玄学比正解快:

 /*莫名打的玄学复杂度bfs,结果ac——by 520*/
#include<bits/stdc++.h>
#define il inline
using namespace std;
const int maxn = ;
int maxlen=,rd[maxn],a[maxn];
vector<int>v[maxn];
il int gi()
{
int a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=;
while(x>=''&&x<='')a=a*+x-,x=getchar();
return f?-a:a;
}
struct node{
int x;
int len;
int gcd;
};
il void bfs(int x,int len,int gcd)
{
node n1,n2;
queue<node>q;
n1.x=x; n1.len=len; n1.gcd=gcd;
q.push(n1);
while(!q.empty())
{
node n1=q.front(); q.pop();
int nx=n1.x, nlen=n1.len, ngcd=n1.gcd;
maxlen=max(nlen, maxlen);
for(int i=;i<v[nx].size();i++)
{
int next=v[nx][i], usegcd=__gcd(a[next],ngcd);
if(usegcd==){
n2.gcd=a[next]; n2.len=; n2.x=next;
q.push(n2);
}
else{
n2.gcd=usegcd; n2.len=+nlen; n2.x=next;
q.push(n2);
}
}
}
}
int main()
{
freopen("deeeep.in","r",stdin);
freopen("deeeep.out","w",stdout);
int x,y,n=gi(),go=;
for(int i=;i<=n;i++)
{
x=gi(),y=gi();
v[x].push_back(y);
rd[y]++;
}
for(int i=;i<=n;i++)
{
if(rd[i]==)go=i;
a[i]=gi();
}
bfs(go,,a[go]);
printf("%d",maxlen);
return ;
}

正解:

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
int n,m,cnt,ans,tot,mor;
const int maxn=;
int to[maxn<<],nxt[maxn<<],head[maxn],v[maxn],d1[maxn],d2[maxn],p[],fa[maxn],dep[maxn],pri[];
bool np[];
vector<int> s[];
map<int,int> mp;
int rd()
{
int ret=; char gc=getchar();
while(gc<''||gc>'') gc=getchar();
while(gc>=''&&gc<='') ret=ret*+gc-'',gc=getchar();
return ret;
}
void dfs(int x)
{
for(int i=head[x];i!=-;i=nxt[i]) if(to[i]!=fa[x]) fa[to[i]]=x,dep[to[i]]=dep[x]+,dfs(to[i]);
}
bool cmp1(int a,int b)
{
return s[a].size()>s[b].size();
}
bool cmp2(int a,int b)
{
return dep[a]>dep[b];
}
void updata(int a,int b)
{
if(d1[b]>d1[a]) d2[a]=d1[a],d1[a]=d1[b];
else d2[a]=max(d2[a],d1[b]);
}
void add(int a,int b)
{
to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
}
int main()
{
freopen("deeeep.in","r",stdin);
freopen("deeeep.out","w",stdout);
n=rd();
int i,j,a,b;
memset(head,-,sizeof(head));
for(i=;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
for(i=;i<=n;i++) v[i]=rd(),m=max(m,v[i]);
m=ceil(sqrt(1.0*m));
for(i=;i<=m;i++)
{
if(!np[i]) pri[++tot]=i,mp[i]=tot;
for(j=;j<=tot&&i*pri[j]<=m;j++)
{
np[i*pri[j]]=;
if(i%pri[j]==) break;
}
}
dep[]=,dfs(),mor=tot;
for(i=;i<=n;i++)
{
for(j=;j<=tot&&pri[j]*pri[j]<=v[i];j++)
{
if(v[i]%pri[j]==)
{
s[j].push_back(i);
while(v[i]%pri[j]==) v[i]/=pri[j];
}
}
if(v[i]>)
{
if(mp.find(v[i])==mp.end()) mp[v[i]]=++mor;
s[mp[v[i]]].push_back(i);
}
}
ans=;
for(i=;i<=mor;i++) p[i]=i;
sort(p+,p+mor+,cmp1);
for(i=;i<=mor;i++)
{
b=p[i];
if(s[b].size()<=ans) break;
sort(s[b].begin(),s[b].end(),cmp2);
for(j=;j<s[b].size();j++) a=s[b][j],d1[a]++,d2[a]++,ans=max(ans,d1[a]+d2[a]-),updata(fa[a],a);
for(j=;j<s[b].size();j++) a=s[b][j],d1[a]=d2[a]=d1[fa[a]]=d2[fa[a]]=;
}
printf("%d",ans);
return ;
}

520的信心赛——点点玩deeeep的更多相关文章

  1. 「THP3考前信心赛」解题报告

    目录 写在前面&总结: T1 T2 T3 T4 写在前面&总结: \(LuckyBlock\) 良心出题人!暴力分给了 \(120pts\) \(T1\) 貌似是个结论题,最后知道怎么 ...

  2. 「THP3考前信心赛」题解

    目录 写在前面 A 未来宇宙 B 空海澄澈 C 旧约酒馆 算法一 算法二 D 博物之志 算法一 算法二 算法三 写在前面 比赛地址:THP3 考前信心赛. 感谢原出题人的贡献:第一题 CF1422C, ...

  3. 2015 HDU 计算机学院 院赛 1003 玩骰子

    Problem Description   Nias与Ains都特别喜欢玩骰子,而且都自以为比对方玩得更溜.  终于有一天,他们决定用骰子来一决高下!  一般的骰子玩法已经不足以体现他们的水平了,于是 ...

  4. pat 团体天梯赛 L2-011. 玩转二叉树

    L2-011. 玩转二叉树 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜 ...

  5. 繁华模拟赛 Evensgn玩序列

    #include<iostream> #include<cstdio> #include<string> #include<cstring> #incl ...

  6. 20220303模拟赛题解and总结

    目录 总结 A.不幸的7 B.选举 C. 差的绝对值之和 D. 路径通过 总结 初一第一 一般,最后一题没打好 不难发现,教练出水了,可能是信心赛 A.不幸的7 暴力,没有逻辑可言 #include& ...

  7. N(C)O(S)I(P)P 2019 退役记

    N(C)O(S)I(P)P 2019 退役记 day-4 今天下午老师突然咕了,于是一下午欢乐时光 今天上午考试T3线段树维护个区间加,区间乘 一遍过编译,一遍过样例(第一次,俺比较弱(虽然也发现和暴 ...

  8. [日常] NOIP前集训日记

    写点流水账放松身心... 10.8 前一天考完NHEEE的一调考试终于可以开始集训了Orz (然后上来考试就迟到5min, GG) T1维护队列瞎贪心, 过了大样例交上去一点也不稳...T出翔只拿了5 ...

  9. HEOI2017 游记

    你若安好,便是晴天. …… 人就像命运下的蝼蚁,谁也无法操控自己的人生. ——阮行止 …… Day 0 中午就要出发了,上午教练还搞了一场欢乐信心赛,然而还是挂惨了.T3是bzoj的原题,但是当时写的 ...

随机推荐

  1. 【转载】图说C++对象模型:对象内存布局详解

    原文: 图说C++对象模型:对象内存布局详解 正文 回到顶部 0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看.本文的结论都在 ...

  2. 3809: Gty的二逼妹子序列

    3809: Gty的二逼妹子序列 链接 分析: 和这道AHOI2013 作业差不多.权值是1~n的,所以对权值进行分块.$O(1)$修改,$O(\sqrt n)$查询. 代码: #include< ...

  3. apache-kylin-2.5.2-bin-cdh57与cdh-5.13.0集群整合运用

    1.下载kylin最新版apache-kylin-2.5.2-bin-cdh57: 2.解压配置环境变量: export BASE_PATH="/opt/cloudera/parcels/C ...

  4. Cocoa Touch提供了哪几种Core Animation过渡类型?

    过渡动画通过 type 设置不同的动画效果, CATransition 有多种过渡效果, 但其实 Apple 官方的SDK只提供了四种: fade 淡出 默认 moveIn 覆盖原图 push 推出 ...

  5. nginx基础配置加基础实战演示

    目录 基本配置 设置用户 工作衍生进程数 错误日志存放路径 pid文件存放路径 设置最大连接数 http->server gzip 字符编码 nginx的基本格式 实战配置 虚拟主机配置 开始配 ...

  6. Valgrind 简单用法

    有时需要给自己写的小程序做个简单的 benchmark,查看内存使用情况和运行时间.这时可以试试 valgrind. Ubuntu 下安装很简单: sudo apt-get update sudo a ...

  7. golang笔记1

    golang笔记1 go代码是用包来组织的,每个包有一个或多个go文件组成,这些go文件文件放在一个文件夹中 每个源文件开始都用一个package声明,指明本源文件属于哪个包 pakage声明后紧跟这 ...

  8. mysql系列学习

    # 帮助help create user;# 查看当前用户select user();# 创建用户create user 'egon'@'localhost' identified by '123'; ...

  9. 亚马逊AWS业务副总裁:如何在基础设施上降成本

    腾讯科技 林靖东 11月17日编译 亚马逊Amazon Web Services业务的副总裁.著名工程师詹姆斯汉密尔顿(James Hamilton)在AWS re:Invent大会上解释了公司是如何 ...

  10. CF刷刷水题找自信1

    CF 1108A Two distinct points 题目意思:给你两个线段的起点和终点,让你给出两个不同的点,这两点分别处于两个不同的线段之中.解题思路:题目说如果存在多种可能的点,随意一组答案 ...