原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1601.html

题目传送门 - 51Nod1601

题意

题解

  首先我们考虑如何求答案。

  我们将所有数字按照二进制位从高到低建到 Trie 上,按照 kruscal 思想,我们要保证先选较小的边。

  于是我们很容易得出结论:在 Trie 上,设 $f(x) =$ 合并子树 $x$ 的所有叶子节点的代价,设 $L(x),R(x)$ 分别为 $x$ 的左右子树编号,则 $f(x)=f(L(x))+f(R(x))+Connect(L(x),R(x))$ 。其中 $Connect(a,b)$ 表示在 $a$ 的叶子节点中 和 $b$ 的叶子节点中各选择一个节点,并将他们相连,需要的最小代价。

  这个显然非常容易求。

  最后我们还有一个问题,就是当递归到 Trie 的叶子节点之后,我们发现它们代表的数字全部相同,连任意一条边的代价为 $0$ ,求把它们连成一棵树的方案,就相当于有 $k$ 个点的无根树计数。有一个东西叫做 pruffer 编码,通过这个东西可以得到 $k$ 个点的互不相同的带标号无根树个数为 $k^{k-2}$ 。

  于是问题就解决了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005,S=N*30,mod=1e9+7;
LL read(){
LL x=0,f=1;
char ch=getchar();
while (!isdigit(ch)&&ch!='-')
ch=getchar();
if (ch=='-')
f=-1,ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x*f;
}
int Next[S][2],tot[S],depth[S],flag[S],cnt=1;
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=1LL*x*x%mod)
if (y&1)
ans=1LL*ans*x%mod;
return ans;
}
LL ans1=0,ans2=1;
void build(int v){
int x=1,t;
for (int i=29;i>=0;i--){
t=(v>>i)&1;
if (!Next[x][t])
Next[x][t]=++cnt;
x=Next[x][t];
depth[x]=i,flag[x]=t;
}
tot[x]++;
}
int mindif,situ;
void Min_Cost_Merge(int x,int y,int dif){
dif|=(flag[x]^flag[y])<<depth[x];
int f=0;
for (int k=0;k<2;k++){
for (int t=0;t<2;t++)
if (Next[x][t]>0&&Next[y][t^k]>0)
Min_Cost_Merge(Next[x][t],Next[y][t^k],dif),f=1;
if (f)
return;
}
if (dif<mindif)
mindif=dif,situ=0;
if (dif==mindif)
situ=(1LL*tot[x]*tot[y]+situ)%mod;
}
int solve(int x){
if (!x)
return 0;
int s=solve(Next[x][0])+solve(Next[x][1]);
if (s==0&&tot[x]>1)
ans2=1LL*ans2*Pow(tot[x],tot[x]-2)%mod;
if (s==2){
mindif=1<<30,situ=1;
Min_Cost_Merge(Next[x][0],Next[x][1],0);
ans1+=mindif,ans2=1LL*ans2*situ%mod;
}
return 1;
}
int main(){
memset(tot,0,sizeof tot);
memset(Next,0,sizeof Next);
for (int i=1,n=read();i<=n;i++)
build(read());
solve(1);
printf("%lld\n%lld",ans1,ans2);
return 0;
}

  

51Nod1601 完全图的最小生成树计数 Trie Prufer编码的更多相关文章

  1. 51Nod1601 完全图的最小生成树计数

    传送门 我居然忘写题解啦!(记忆废) 不管怎么说,这题还算是一道好题啊……你觉得敦爷出的题会有水题么 …… 这题比较容易把人误导到Boruvka算法之类的东西上去(我们机房去刚D题的人一开始大多也被误 ...

  2. Luogu2290 [HNOI2004]树的计数 (组合计数,prufer编码)

    这不prufer编码吗,防爆long long就行了啊 #include <iostream> #include <cstdio> #include <cstring&g ...

  3. 「51Nod 1601」完全图的最小生成树计数 「Trie」

    题意 给定\(n\)个带权点,第\(i\)个点的权值为\(w_i\),任意两点间都有边,边权为两端点权的异或值,求最小生成树边权和,以及方案数\(\bmod 10^9 + 7\) \(n \leq 1 ...

  4. 51Nod 1601 完全图的最小生成树计数

    题目链接 分析: 这是一张完全图,并且边的权值是由点的权值$xor$得到的,所以我们考虑贪心的思想,考虑$kruskal$的过程选取最小的边把两个连通块合并,所以我们可以模仿$kruskal$的过程, ...

  5. 【BZOJ1211】树的计数(Prufer编码)

    题意:一个有n个结点的树,设它的结点分别为v1, v2, …, vn, 已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵. 其中1<=n<=150,输入数据保证满足条件的 ...

  6. 树的Prufer 编码和最小生成树计数

      Prufer数列 Prufer数列是无根树的一种数列.在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2.它可以通过简单的迭代方 ...

  7. bzoj1211: [HNOI2004]树的计数 prufer编码

    题目链接 bzoj1211: [HNOI2004]树的计数 题解 prufer序 可重排列计数 代码 #include<bits/stdc++.h> using namespace std ...

  8. prufer编码

    看51nod的一场比赛,发现不会大家都A的一道题,有关prufer的 我去年4月就埋下prufer这个坑,一直没解决 prufer编码是什么 对于一棵无根树的生成的序列,prufer序列可以和无根树一 ...

  9. [bzoj1005][HNOI2008]明明的烦恼-Prufer编码+高精度

    Brief Description 给出标号为1到N的点,以及某些点最终的度数,允许在 任意两点间连线,可产生多少棵度数满足要求的树? Algorithm Design 结论题. 首先可以参考这篇文章 ...

随机推荐

  1. MySQL建库建表

    一直使用SQL SERVER 数据库:最近项目使用MY SQL感觉还是有一点不适应.不过熟悉之后就会好很多. MY SQL 安装之后会有一个管理工具MySQL Workbench 感觉不太好用,数据库 ...

  2. dnsmasq详解&手册

    Dnsmasq为小型网络提供网络基础设施:DNS,DHCP,路由器通告和网络引导.它被设计为轻量级且占用空间小,适用于资源受限的路由器和防火墙.它还被广泛用于智能手机和便携式热点的共享,并支持虚拟化框 ...

  3. chrome调试工具怎么限制网速

    在做项目的时候,我们测试的时候有时需要限制网速

  4. Confluence 6 通过 SSL 或 HTTPS 运行 - 确定你的证书路径

    在默认的情况下,Tomcat 希望 keystore 文件被命名为 .keystore 文件,同时这个文件应该放置在 Tomcat 运行的 home 目录中(这个目录可能与你自己的 Home 目录的路 ...

  5. Confluence 6 附件存储文件系统的分级

    从 Confluence 3.0 开始,附件的存储方式有了重大的改变和升级.如果你是从 Confluence 2.10 及其早期版本升级上来的,请参考 Upgrading Confluence 页面中 ...

  6. EasyUI Layout 布局

    1.在整个页面上创建布局(Layout) <!DOCTYPE html> <html> <head> <title>吹泡泡的魚-主页</title ...

  7. Saruman's Army(POJ3069)

    Description Saruman the White must lead his army along a straight path from Isengard to Helm’s Deep. ...

  8. Django入门基础详解

    本次使用django版本2.1.2 安装django 安装最新版本 pip install django 安装指定版本 pip install django==1.10.1 查看本机django版本 ...

  9. 开始接触python

    1.什么是语言? 语言是一个事物与另一个事物交流的介质 python是人与计算机交流的介质 能够被计算机所识别的表达方式即是编程语言 2.什么是编程? 编程就是程序员将想让计算机做的事情用编程语言表达 ...

  10. 无废话-API-01

    说明 我的开发环境:VS2013 浏览器:谷歌浏览器(Google Chrome) 1创建项目 1.1添加一个 应用程序"ASP.NET MVC 4 Web 应用程序"  1.2选 ...