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 ...
随机推荐
- 反转链表_JAVA
package algorithms; /* * * * 输入一个链表,反转链表后,输出新链表的表头. * public class ListNode { int val; ListNode next ...
- Python学会之后,一般能拿到多少工资?
Python在约40年前出现以来,已经有数以千计基于这项技术的网站和软件项目,Python因其独有的特点从众多开发语言中脱颖而出,深受世界各地的开发者喜爱. 随着Python的技术的流行,Python ...
- UVALIVE6886 Golf Bot (FFT)
题意:打高尔夫 给你n个距离表示你一次可以把球打远的距离 然后对于m个询问 问能否在两杆内把球打进洞 题解:平方一下就好 注意一下x0的系数为1表示打一杆 才发现数组应该开MAXN * 4 之前写的题 ...
- Day 14B 网络应用开发
网络应用开发 发送电子邮件 在即时通信软件如此发达的今天,电子邮件仍然是互联网上使用最为广泛的应用之一,公司向应聘者发出录用通知.网站向用户发送一个激活账号的链接.银行向客户推广它们的理财产品等几乎都 ...
- 参考KOA,5步手写一款粗糙的web框架
我经常在网上看到类似于KOA VS express的文章,大家都在讨论哪一个好,哪一个更好.作为小白,我真心看不出他两who更胜一筹.我只知道,我只会跟着官方文档的start做一个DEMO,然后我就会 ...
- 关于Extjs的窗口拖拽,改变大小,背景淡化问题
大部分Extjs的Windows问题:在Extjs4代码中,只要加几句话: frame:true, //这个窗口的边边是圆的 border : false , //窗口没有边框 draggable: ...
- python3 时间模块 random模块之两个小练习
话不多说,一个是算时间的,还有一个是生成验证码的 #!usr/bin/env/ python # -*- coding:utf-8 -*- # Author: XiaoFeng import time ...
- python爬虫28 | 你爬下的数据不分析一波可就亏了啊,使用python进行数据可视化
通过这段时间 小帅b教你从抓包开始 到数据爬取 到数据解析 再到数据存储 相信你已经能抓取大部分你想爬取的网站数据了 恭喜恭喜 但是 数据抓取下来 要好好分析一波 最好的方式就是把数据进行可视化 这样 ...
- Ubuntu挂载硬盘,修改卷标
Ubuntu挂载硬盘,修改卷标转载2016-03-06 17:03:21标签:ubuntu Ubuntu不像windows,硬盘插入电脑不会自动读取硬盘 数据,需要把硬盘挂载到文件夹上,然后才能访问硬 ...
- Python学习笔记 (2)变量、常量和数据类型
变量 顾名思义,变量就是一个会变的量,用一个变量名表示,指向内存中一片区域,而指向的区域存的是什么,这个变量就是什么数据类型,和C/C++挺不一样的.变量数据类型可以通过赋值变来变去(这就叫动态语言, ...