NOI.AC #31. MST
好像又是神仙dp。。。。gan了一早上
首先这是个计数类问题,上DP,
对于一个最小生成树,按照kruskal是一个个联通块,枚举边小到大合成的
假如当前边是树边,那么转移应该还是枚举两个块然后合并
假如不是树边那么就在所有联通块所有非树边中任选一条
两个相邻树边之间的非树边方案应该是P(所有联通块总边数-(当前枚举到那条边-1),r-l-1)
然而按照我现在的智商还是不会捉
%了题解发现一个非常强大的性质,就是对于一个整数的无序拆分很小,40只有37338
设f[zt],其中zt表示一个状态,由一些联通块的大小组成,总和为n
这样可以爆搜一波把所有无序拆分也就是状态弄出来,并给一个新编号
转移就是枚举两个联通块然后合并
若第i,j个合并
(新状态的方案)+=(这个状态的方案)*(两条树边之间其他边选择的方案)*(第i个联通块的大小)*(第j个联通块的大小)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
const LL mod=1e9+; int n;
struct zhuangtai
{
int u[];
friend bool operator >(zhuangtai z1,zhuangtai z2)
{
if(z1.u[]==z2.u[])
{
for(int i=;i<=z1.u[];i++)
if(z1.u[i]!=z2.u[i])return z1.u[i]>z2.u[i];
}
return z1.u[]>z2.u[];
}
friend bool operator <(zhuangtai z1,zhuangtai z2)
{
if(z1.u[]==z2.u[])
{
for(int i=;i<=z1.u[];i++)
if(z1.u[i]!=z2.u[i])return z1.u[i]<z2.u[i];
}
return z1.u[]<z2.u[];
}
int getsum()
{
int ret=;
for(int i=;i<=u[];i++)
ret=(ret+(u[i]*(u[i]-)/)%mod)%mod;
return ret;
}
}mp[];int z,g[];
bool cmp(zhuangtai z1,zhuangtai z2){return z1>z2;}
map<zhuangtai,int>id;//通过状态找编号
void dfs(int d,int last)//预处理拆分n的方案
{
if(d==n)
{
z++;
for(int i=;i<=g[];i++)mp[z].u[i]=g[i];
return ;
}
for(int i=last;i+d<=n;i++)
{
g[++g[]]=i;
dfs(i+d,i);
g[g[]--]=;
}
} LL quick_pow(LL A,LL p)
{
LL ret=;
while(p!=)
{
if(p%==)ret=ret*A%mod;
A=A*A%mod;p/=;
}
return ret;
}
LL fac[],fac_inv[];
LL getP(int n,int m){return fac[n]*fac_inv[n-m]%mod;} zhuangtai t;int h[];
int getnzt(int zt,int x,int y)
{
memcpy(h,mp[zt].u,sizeof(h));
int d=h[x]+h[y]; memset(t.u,,sizeof(t.u));
for(int i=;i<=h[];i++)
{
if(i!=x&&i!=y)
{
if(d!=-&&h[i]>d)t.u[++t.u[]]=d,d=-;
t.u[++t.u[]]=h[i];
}
}
if(d!=-)t.u[++t.u[]]=d;
return id[t];
}
int a[];LL f[];
int main()
{
fac[]=,fac_inv[]=;
for(int i=;i<=;i++)
fac[i]=fac[i-]*i%mod,fac_inv[i]=quick_pow(fac[i],mod-); scanf("%d",&n);
for(int i=;i<n;i++)scanf("%d",&a[i]);
z=;dfs(,);
sort(mp+,mp+z+,cmp);
for(int i=;i<=z;i++)id[mp[i]]=i; memset(f,,sizeof(f));f[]=;
for(int zt=;zt<=z;zt++)
if(f[zt]>)
{
int e=n-mp[zt].u[]+;//轮到第几条边用来合并
LL P=getP(mp[zt].getsum()-(a[e-]),a[e]-a[e-]-);//两条树边中间其他边选择的方案数 for(int i=;i<=mp[zt].u[];i++)
for(int j=i+;j<=mp[zt].u[];j++)
{
int nzt=getnzt(zt,i,j);
f[nzt]=(f[nzt]+f[zt]*P%mod*mp[zt].u[i]%mod*mp[zt].u[j]%mod)%mod;
}
}
int rst=n*(n-)/-a[n-];
printf("%lld\n",f[z]*getP(rst,rst)%mod);
return ;
}
NOI.AC #31. MST的更多相关文章
- NOI.AC #31 MST —— Kruskal+点集DP
题目:http://noi.ac/problem/31 好题啊! 题意很明白,对于有关最小生成树(MST)的题,一般是要模拟 Kruskal 过程了: 模拟 Kruskal,也就是把给出的 n-1 条 ...
- NOI.ac #31 MST DP、哈希
题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...
- NOI.AC 31 MST——整数划分相关的图论(生成树、哈希)
题目:http://noi.ac/problem/31 模拟 kruscal 的建最小生成树的过程,我们应该把树边一条一条加进去:在加下一条之前先把权值在这一条到下一条的之间的那些边都连上.连的时候要 ...
- [NOI.AC#31]MST 计数类DP
链接 注意到 \(n\) 只有40,爆搜一下发现40的整数拆分(相当于把 \(n\) 分成几个联通块)很少 因此可以枚举联通块状态来转移,这个状态直接用vector存起来,再用map映射,反正40也不 ...
- noi.ac #39 MST
MST 模板题 #include <iostream> #include <cstdio> #include <algorithm> #include <cm ...
- NOI.AC NOIP模拟赛 第六场 游记
NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...
- # NOI.AC省选赛 第五场T1 子集,与&最大值
NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...
- NOI.AC NOIP模拟赛 第五场 游记
NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...
- NOI.AC NOIP模拟赛 第二场 补记
NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...
随机推荐
- POJ_2536_Gopher II
题意:n只地鼠,m个地鼠洞,地鼠必须以v的速度在s秒内钻进洞且每个洞仅能容纳一只地鼠,问最少有几只地鼠会被老鹰吃掉. 分析:最大匹配问题,将s秒内地鼠能够跑到的洞与该地鼠连成一条边,在最后得到的图中使 ...
- mysql数据转sql server
创建一个mysql的ODBC数据源,在sql server中“任务”-“导入数据” -“选择创建的ODBC数据源” 然后填写服务器 登录名.密码,需要导入的数据库表什么的
- c++类简介
C++类(Class)总结 一.C++类的定义 C++中使用关键字 class 来定义类, 其基本形式如下:class 类名{ public: //行为或属性 protected: // ...
- Spring框架系列(二)--装配和注入Bean
企业日常开发中,几乎都是Spring系的框架,无论是SSM.还是现在大火的SpringBoot+JPA/MyBatis,使用最大的目的就是简化开发 基本模块: 核心容器:Beans.Core.Cont ...
- HTML5定制全选列头
随着HTML5产品分支的不断深入使用,HTML5的需求也是越来越多,表格组件的使用也不例外,什么排序,分页,自动列宽等.最近有客户提出了如果让表格的列头加上全选的功能.细细分析其实就是两部分,表格的b ...
- C++ CEF 浏览器中显示 Tooltip(标签中的 title 属性)
在 Windows 中将 CEF 集成到 C++ 客户端以后,默认是无法显示 tooltip 的,比如图片标签中的 title 属性. 实现的方式其实很简单,按下面的步骤操作就可以: 创建一个文本文件 ...
- acm相关(纯转载)
我觉得很好的文章,之所以放随笔是为了让大家看到这些优秀的博文 acm如何起步 acm重点题型 动态规划题目总结 背包九讲阅读网站
- 07Html、CSS
07Html.CSS-2018/07/17 1.HTML是用来描述网页的一种标记语言,是一套标记标签.HTML用使用标记标签来描述网页.超文本 标记语言. 2.格式 <html> < ...
- Java8-如何将List转变为逗号分隔的字符串--https://blog.csdn.net/benjaminlee1/article/details/72860845
Java8-如何将List转变为逗号分隔的字符串 https://blog.csdn.net/benjaminlee1/article/details/72860845
- MySql 执行计划解读
说明 解读执行计划l对于我们日常工作中慢sql的分析和调优有很大帮助,同时在解读的过程中也能知道如何规避慢sql 建议需要了解join匹配原理的知识:https://www.cnblogs.com/L ...