AT3728 Squirrel Migration
就是给每个点分配两个匹配点(自环除外)
考虑最大值
考虑极限情况:每个边的贡献是min(sz[u],sz[v])*2
证明存在方案:
发现,如果哪边sz更小,就把这些边都往外连
这样,在重心的位置,会两两匹配闭合。
所以存在构造方案。
方案数?就是最后匹配的方案
重心两个:((n/2)!)^2
重心一个:
也就是,以重心为根,每个子树是一个组,每个组必须匹配别的组
而重心自己可以连自环或者匹配任意一个组
枚举重心连自环与否,做两遍。
现在有若干个组,每个组有num[i]个元素,每个组不能匹配自己的元素
考虑容斥!
f[i][j]前i个组,有j个位置连了自己组的元素的方案数
f[i][j+k]+=f[i-1][j]*C(num[i],k)*A(num[i],k)
看似O(n^3),实际和树形背包的sz优化一样,就是O(n^2)的
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
namespace Modulo{
const int mod=1e9+;
int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
void inc(int &x,int y){x=ad(x,y);}
int mul(int x,int y){return (ll)x*y%mod;}
void inc2(int &x,int y){x=mul(x,y);}
int qm(int x,int y=mod-){int ret=;while(y){if(y&) ret=mul(x,ret);x=mul(x,x);y>>=;}return ret;}
}
using namespace Modulo;
namespace Miracle{
const int N=;
int n;
struct node{
int nxt,to;
}e[*N];
int hd[N],cnt;
int jie[N],inv[N];
int C(int n,int m){
if(n<||m<||n<m) return ;
return mul(jie[n],mul(inv[m],inv[n-m]));
}
int A(int n,int m){
return mul(C(n,m),jie[m]);
}
void add(int x,int y){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
int be[N],sz[N],num[N],tot;
int rt[N];
void dfs(int x,int fa){
sz[x]=;
int mx=;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa) continue;
dfs(y,x);
sz[x]+=sz[y];
if(sz[y]>mx) mx=sz[y];
}
mx=max(mx,n-sz[x]);
if(mx<=n/){
rt[++rt[]]=x;
}
}
void fin(int x,int fa){
be[x]=tot;
++num[be[x]];
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa) continue;
if(x==rt[]){
++tot;
}
fin(y,x);
}
}
int f[N][N];
int calc(){
memset(f,,sizeof f);
f[][]=;
int sum=;
for(reg i=;i<=tot;++i){
// cout<<" i "<<i<<" "<<num[i]<<endl;
for(reg j=;j<=sum;++j){
for(reg k=;k<=num[i];++k){
// cout<<" con "<<mul(f[i-1][j],mul(C(num[i],k),A(num[i],k)))<<endl;
f[i][j+k]=ad(f[i][j+k],mul(f[i-][j],mul(C(num[i],k),A(num[i],k))));
}
}
sum+=num[i];
}
ll ret=;
for(reg j=;j<=sum;++j){
// cout<<f[tot][j]<<endl;
if(j&){
ret=ad(ret,mod-mul(f[tot][j],jie[sum-j]));
}else{
ret=ad(ret,mul(f[tot][j],jie[sum-j]));
}
}
return ret;
}
int main(){
rd(n);
jie[]=;
for(reg i=;i<=n;++i) jie[i]=mul(jie[i-],i);
inv[n]=qm(jie[n]);
for(reg i=n-;i>=;--i) inv[i]=mul(inv[i+],i+);
int x,y;
for(reg i=;i<n;++i){
rd(x);rd(y);
add(x,y);add(y,x);
}
dfs(,);
if(rt[]==){
ll ans=qm(jie[n/],);
ot(ans);return ;
}
// cout<<rt[1]<<endl;
fin(rt[],);
// cout<<" tot "<<tot<<endl;
// prt(be,1,n);
int ans=calc();
// cout<<" ans1 "<<ans<<endl;
num[++tot]=;
ans=ad(ans,calc());
ot(ans);
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
*/
构造最大值,考虑上界,再证明能不能达到。
然后构造方案很明确了,方案数就是分组,容斥DP来处理
AT3728 Squirrel Migration的更多相关文章
- [ARC087D] Squirrel Migration 补题记录
题目链接 简要题意: 给你一个\(N\)个节点的树,求一个\(1\cdots N\)的排列\((p_1,p_2,\cdots p_N)\) ,使得\(\sum dist(i,p_i)\)最大. 求这样 ...
- [atARC087F]Squirrel Migration
对这棵树重心情况分类讨论: 1.若这棵树存在两个重心,分别记作$x$和$y$,如果将$(x,y)$断开,两棵子树大小都相同(都为$\frac{n}{2}$),此时$p_{i}$与$i$必然不同属于一个 ...
- Atcoder 乱做
最近感觉自己思维僵化,啥都不会做了-- ARC103 F Distance Sums 题意 给定第 \(i\) 个点到所有点的距离和 \(D_i\) ,要求构造一棵合法的树.满足第 \(i\) 个点到 ...
- 【AtCoder】ARC087
C - Good Sequence 题解 用个map愉悦一下就好了 代码 #include <bits/stdc++.h> #define fi first #define se seco ...
- 写给.NET开发者的数据库Migration方案
微软给我们提供了一种非常好用的数据库迁移方案,但是我发现周围的同学用的并不多,所以我还是想把这个方案整理一下..NET选手看过来,特别是还在通过手工执行脚本来迁移数据库的同学们,当然你也可以选择EF的 ...
- EF Core 数据库迁移(Migration)
工具与环境介绍 1.开发环境为vs 2015 2.mysql EF Core支持采用 Pomelo.EntityFrameworkCore.MySql 源代码地址(https://github. ...
- Database first with EntityFramework (Migration)安装和升级
最近看了国外几个项目,发现用EntityFramework做Code First的项目现在很流行. 最让我有兴趣的一个功能则是,EntityFramework对于数据库的安装和升级的无缝完美支持,且很 ...
- Squirrel: 通用SQL、NoSQL客户端
安装 配置数据库 配置驱动 配置连接 如果你的工作中,需要使用到多个数据库,又不想在多种客户端之间切换来切换去.那么就需要找一款支持多数据库的客户端工具了.如果你要连接多个关系型数据库,你就可以使用N ...
- Laravel使用笔记 —— migration
在使用 php artisan make:migration 创建migration时,可用 --path 指定创建migration文件的路径, 如果在执行的 php artisan migrate ...
随机推荐
- tesseract训练手写体
前面的步骤都一样,从第4步开始 4.使用tesseract生成.box文件: tesseract eng.handwriting.exp0.tif eng.handwriting.exp0 -l en ...
- netbeans调试webapp 只能用localhost访问
etbeans 我的电脑是192.168.0.2,用这个地址访问 网上有人说,分两种情况 此问题分两种情况: 1. 可以用127.0.0.1访问 2. 不能用127.0.0.1访问 针对第一种情况,我 ...
- BZOJ4719[NOIP2016提高组Day1T2] 天天爱跑步
#261. [NOIP2016]天天爱跑步 描述 提交 自定义测试 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家 ...
- idea展开和折叠方法的快捷键
Ctrl+"+/-",当前方法展开.折叠 Ctrl+Shift+"+/-",全部展开.折叠
- Android中使用ormlite实现持久化--HelloOrmLite
Android中内置了sqlite,但是常用的开发语言java是面向对象的,而数据库是关系型的,二者之间的转化每次都很麻烦(主要是我对sql语言不熟悉).而Java Web开发中有很多orm框架,但是 ...
- 【JZOJ5081】【GDSOI2017第三轮模拟】Travel Plan 背包问题+双指针+树的dfs序
题面 100 注意到ban的只会是一个子树,所以我们把原树转化为dfs序列. 然后题目就转化为,询问一段ban的区间,之后的背包问题. 比赛的时候,我想到这里,于是就开始想区间合并,于是搞了线段树合并 ...
- web标准中定义id与class有什么区别吗
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x ...
- 逐行粒度的vuex源码分析
vuex源码分析 了解vuex 什么是vuex vuex是一个为vue进行统一状态管理的状态管理器,主要分为state, getters, mutations, actions几个部分,vue组件基于 ...
- 如何用最暴力的方法改写Liferay的原生portlet
最近在论坛上看到有人问如何改写Liferay原有的calendar portlet. 然后研究了一下,直接从portal中把calendar portlet的源码拷贝出来,然后修改再部署上去,但是这个 ...
- CNCF 旗下首个为中国开发者量身打造的云原生课程,《CNCF x Alibaba 云原生技术公开课》即将上线
伴随着以 Kubernetes 为代表的云原生技术体系的日益成熟以及 CNCF 生态的逐渐壮大,“云原生”已然成为了未来云计算时代里一个当仁不让的关键词.但是,到底什么是“云原生”?云原生与 CNCF ...