题目描述

牛牛在纸上画了\(N\)个点(从\(1\)到\(N\)编号),每个点的颜色用一个整数描述。

牛牛决定用这\(N\)个点随机生成一棵树,生成的规则如下:

  1. \(1\)号点是根节点
  2. 对于\(2\)号点到\(N\)号点,每个点随机指定一个父亲。\(i\)号点(\(2 \leq i \leq N)\)的父亲在i的约数中随机挑选一个。(例如\(10\)号点的父亲可以是\(1\)号,\(2\)号,\(5\)号,\(7\)号点的父亲只能是\(1\)号点)树生成完之后,牛牛可以计算出这个树有多少个联通块,一个联通块是一些点的集合,需要满足以下两个条件:
    • 从集合中任取两个点都满足:两个点颜色相同,且这两个点之间存在一条树边组成的路径,路径上的所有点都和这两个点颜色相同
    • 对于集合中的任意一个点和集合外的任意一个点:两点要么不同色,要么不存在一条树边组成的路径使得路径上所有点都和这两个点同色。

牛牛希望计算出生成的树中最多有多少个联通块

输入描述:

第一行一个整数\(N\)代表点数

第二行\(N\)个整数,第\(i\)个整数\(c_i\)代表第\(i\)个点的颜色

对于\(30\%\)的数据, \(2 \leq N \leq 10\), \(颜色1 \leq \text{颜色} \leq 5\)

对于\(60\%\)的数据, \(2 \leq N \leq 5000\),$颜色1 \leq \text{颜色} \leq $5000

对于\(80\%\)的数据, \(2 \leq N \leq 200000\), \(颜色1 \leq \text{颜色} \leq 10^9\)

对于\(100\%\)的数据, \(2 \leq N \leq 500000\), \(颜色1 \leq \text{颜色} \leq 10^9\)

输出描述:

输出一个整数最多有多少联通块

示例1

输入

4
1 1 1 2

输出

2

说明

\(2\)号点和\(3\)号点的父亲一定是\(1\),\(4\)号点父亲可能是\(1\)或者\(2\),两种情况下联通块数都是\(2\)

Solution

通过打暴力时候的一个操作发现解法。

我们发现,一个点的颜色只要与其父节点不同,那么联通块就会多一个,否则不变。

因此,我们只需要对于一个数,枚举其所有可行的父节点 ,只要颜色不一样就可以加。

然而这样是\(O(n^2)\)的。

这里有一个技巧:我们化枚举因数为枚举倍数。

for(int i=1;i<=n;++i)
for(int j=i+i;j<=n;j+=i);

这个东西的时间复杂度为\(O(n\log n)\)

因为这个东西需要执行的次数为

\[\frac n1+\frac n2+\frac n3+...+\frac nn=n(\frac11+\frac12+\frac13+...+\frac1n)=n(\ln(n+1)+r)
\]

其中\(r\)为欧拉常数,近似值为$0.5772156649 $。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define REP(i,a,n) for(register int i=(a);i<=(n);++i)
#define PER(i,a,n) for(register int i=(a);i>=(n);--i)
#define FEC(i,x) for(register int i=head[x];i;i=g[i].ne)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
namespace io{
const int SIZE=(1<<21)+1;char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];int f,qr;
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
inline void putc(char x){*oS++=x;if(oS==oT)flush();}
template<class I>inline void read(I &x){for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;}
template<class I>inline void write(I x){if(!x)putc('0');if(x<0)putc('-'),x=-x;while(x)qu[++qr]=x%10+'0',x/=10;while(qr)putc(qu[qr--]);}
inline void print(const char *s){while(*s!='\0')putc(*s++);}
inline void scan(char *s){for(c=gc();c<=' ';c=gc());for(;c>' ';c=gc())*(s++)=c;*s='\0';}
struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}//orz laofudasuan
using io::read;using io::putc;using io::write;using io::print;
typedef long long ll;typedef unsigned long long ull;
template<typename A,typename B>inline bool SMAX(A&x,const B&y){return x<y?x=y,1:0;}
template<typename A,typename B>inline bool SMIN(A&x,const B&y){return y<x?x=y,1:0;} const int N=500000+7;
int n,a[N],ans=1,fst[N]; int main(){
#ifndef ONLINE_JUDGE
freopen("B.in","r",stdin);freopen("B.out","w",stdout);
#endif
read(n);for(register int i=1;i<=n;++i)read(a[i]);
for(register int i=1;i<=n;++i)
for(register int j=i+i;j<=n;j+=i)
SMAX(fst[j],a[i]!=a[j]);
for(register int i=2;i<=n;++i)ans+=fst[i];
write(ans),putc('\n');
}

牛客网NOIP赛前集训营-提高组(第七场)B-随机生成树的更多相关文章

  1. 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告

    目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...

  2. 牛客网NOIP赛前集训营-提高组(第二场)A 方差

    链接:https://www.nowcoder.com/acm/contest/173/A来源:牛客网 题目描述 一个长度为 m 的序列 b[1...m] ,我们定义它的方差为 ,其中  表示序列的平 ...

  3. [牛客网NOIP赛前集训营-提高组(第一场)]C.保护

    链接:https://www.nowcoder.com/acm/contest/172/C来源:牛客网 题目描述 C国有n个城市,城市间通过一个树形结构形成一个连通图.城市编号为1到n,其中1号城市为 ...

  4. 牛客网NOIP赛前集训营-提高组(第一场)

    牛客的这场比赛感觉真心不错!! 打得还是很过瘾的.水平也比较适合. T1:中位数: 题目描述 小N得到了一个非常神奇的序列A.这个序列长度为N,下标从1开始.A的一个子区间对应一个序列,可以由数对[l ...

  5. 比赛总结——牛客网 NOIP赛前集训营提高组模拟第一场

    第一场打的很惨淡啊 t1二分+前缀最小值没想出来,20分的暴力也挂了,只有10分 t2数位dp,调了半天,结果因为忘了判0的特殊情况WA了一个点,亏死 t3emmmm.. 不会 imone说是DSU ...

  6. 牛客网NOIP赛前集训营-提高组(第一场)B 数数字

    数数字 思路: 数位dp 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ...

  7. 牛客网NOIP赛前集训营-提高组(第一场)A 中位数

    中位数 思路: 二分答案 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ...

  8. 牛客网NOIP赛前集训营 提高组 第5场 T2 旅游

    [题解] 我们可以发现不在最小生成树上的边一定不能多次经过,因为一条不在最小生成树上的边(u,v)的边权比最小生成树上(u,v)之间的路径更长,选择不在最小生成树上的边一定不划算. 我们还需要确定最小 ...

  9. 牛客网NOIP赛前集训营-提高组(第四场)游记

    牛客网NOIP赛前集训营-提高组(第四场)游记 动态点分治 题目大意: \(T(t\le10000)\)组询问,求\([l,r]\)中\(k(l,r,k<2^{63})\)的非负整数次幂的数的个 ...

  10. 牛客网NOIP赛前集训营-提高组(第四场)B区间

    牛客网NOIP赛前集训营-提高组(第四场)B区间 题目描述 给出一个序列$ a_1  \dots   a_n$. 定义一个区间 \([l,r]\) 是好的,当且仅当这个区间中存在一个 \(i\),使得 ...

随机推荐

  1. Oracle中动态SQL详解(EXECUTE IMMEDIATE)

    Oracle中动态SQL详解(EXECUTE IMMEDIATE) 2017年05月02日 18:35:48 悠悠倾我心 阅读数:744 标签: oracle动态sqloracle 更多 个人分类:  ...

  2. C语言 | 线段树

    #include<stdio.h> #define MAX_LEN 1000 void build_tree(int arr[],int tree[],int node,int start ...

  3. ICMP(Internet Control Message Protocol)网际控制报文协议初识

    ICMP是(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议族的一个子协议,用于在IP主机.路由器之间传递控制消息.控制消息是指网 ...

  4. Elasticsearch6.5安装&&常见问题与答案解释

    ElasticSearch是一个用Java开发的基于Lucene的搜索服务器.它可以提供一个分布式多用户能力的全文搜索引擎,基于RESTfulweb接口.现阶段它主要为Apache许可条款下的开放源码 ...

  5. nginxUbuntu安装Nginx和正确卸载Nginx Nginx相关 与Nginx报错:nginx: [error] invalid PID number "" in "/run/nginx.pid" 解决方法

    https://www.cnblogs.com/zhaoyingjie/p/6840616.html https://blog.csdn.net/adley_app/article/details/7 ...

  6. python学习笔记:unittest单元测试

    单元测试:开发自测时写的代码 unittest基本原理: ♦整个平台的搭建使用的是python的unittest测试框架,这里简单介绍下unittest模块的简单应用. ♦unittest是pytho ...

  7. C# 文件、byte相互转换

    文件转byte数组: /// <summary> /// 将文件转换为byte数组 /// </summary> /// <param name="path&q ...

  8. Spring数据库连接池 c3p0、dbcp、spring-jdbc

    在用dbcp的时候 后面加上 destroy-method="close" 销毁的方法没事 但是用 spring的jdbc就会报错 提示找不到close这个方法  这是为什么? D ...

  9. 解决ubuntu下eth0不显示

    今天电脑重启之后,用ifconfig查看网络地址,就发现eth0神奇的消失了,顿时感觉吓尿了. 按照网上看到的资料,发现输入ifconfig -a 发现可以显示eth0,但是当输入ifconfig就没 ...

  10. Vue的入门之安装

    vue.js是前端框架中比较热门的,因为工作关系,也加入了浩浩荡荡的学习大潮中,用笔记记录下点滴,便于后面学习查阅! 1 node.js环境的安装包(npm包管理器) 2 vue-cli 脚手架构建工 ...