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 ...
随机推荐
- 更新dell机器的idrac的固件版本后重启机器系统失败
事情是这样的.dell ra620机器,idrac7打不开java,所以在机器生产中直接更新了固件,客户直接在系统内reboot后就连不上.打开本地是卡在下图. 强制重启后发现服务器提示,是IDRAC ...
- 梦想CAD控件自定义实体实现
一.增加自定义实体对象 调用DrawCustomEntity函数,绘制一个自定义实体对象. 下面代码绘制一个自定义实体,C#代码实现如下: private void DrawMlineCommand( ...
- 梦想Android版CAD控件2018.7.26更新
下载地址: http://www.mxdraw.com/ndetail_109.html 1. 增加所有接口CHM帮助文档 2. 增加得到当前打开文件函数 3. 读写CAD扩展记录接口 4. 读写属性 ...
- 【原】Mysql常用语句
1.修改编码方式为UTF-8 ALTER TABLE 表名 CHANGE 列名 新列名 VARCHAR(255) CHARACTER SET utf8 COLLATE ...
- for循环,isinstance() 函数
#isinstance()的运用 #练习: 求值总和以及平均值. str_list = [1,2,3,4,5,6,'a',7,8,9,'b',10,'c'] my_tal = 0 my_var = 0 ...
- Docker 的基本使用
一.简介 Docker 是一个开源的应用容器引擎,基于 Go 语言.Docker 支持将软件编译成一个镜像,然后在镜像中为软件做好配置,将镜像发布出去,其他使用者就可以直接使用这个镜像,而不需再和以前 ...
- Python基础-获取当前目录,上级目录,上上级目录
import os print '***获取当前目录***' print os.getcwd() print os.path.abspath(os.path.dirname(__file__)) pr ...
- 关于 CMSIS 标准 及 STM32F10x的固件库
CMSIS 标准英文全称是Cortex MicroController Software Interface Standard,翻译为中文意思就是 ARM Cortex 微控制器软件接口标准. 由于基 ...
- 【Codeforces 1063B】Labyrinth
[链接] 我是链接,点我呀:) [题意] 你可以往左最多x次,往右最多y次 问你从x,y出发最多能到达多少个格子 只能往上下左右四个方向走到没有障碍的格子 [题解] 假设我们从(r,c)出发想要到固定 ...
- BNUOJ 14381 Wavio Sequence
Wavio Sequence Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVA. Origina ...