题解 CF1540B
前言
不可发送单个标点符号。
思路
不难想到对每个最开始选的点分开考虑。
在选定第一个数后,我们考虑每对数的贡献。
不难发现如果令
- 祖先关系
先取的数已经固定了,贡献只能为
- 非祖先关系。
不难发现在插入它们的 LCA 后,剩下的插入要么与这两个点无关,要么等概率让它们其中的一个距离已选区域距离减
于是,我们可以预处理,插入 LCA 后,两个点需要
时间复杂度
代码
// Problem: CF1540B Tree Array
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1540B
// Memory Limit: 250 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//And in that light,I find deliverance.
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
const int p=1e9+7;
int qp(int x,int y)
{
int res=1;
for(int t=x; y; y>>=1,t=t*t%p) if(y&1) res=res*t%p;
return res;
}
int n=read();
vector<int> e[1003];
int s;
int sz[1003];
int f[1003][1003];
//x steps,y steps,x first
void init(int n)
{
for(int i=1; i<=n; ++i) f[0][i]=1;
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
f[i][j]=(f[i-1][j]+f[i][j-1])*qp(2,p-2)%p;
return ;
}
void getd(int x,int fa,int v)
{
if(x<v) ++s;
for(int i:e[x]) if(i!=fa) getd(i,x,v);
}
void dfs(int x,int fa)
{
getd(x,fa,x);
for(int i:e[x]) if(i!=fa) dfs(i,x);
}
vector<pair<int,int> > c[1003];
void calc(int x,int fa,int id,int d)
{
for(pair<int,int> i:c[id]) if(x>i.first)
s=(s+f[d][i.second])%p;
else s=(s+f[i.second][d])%p;
for(int i:e[x]) if(i!=fa) calc(i,x,id,d+1);
}
void add(int x,int fa,int id,int d)
{
c[id].push_back(make_pair(x,d));
for(int i:e[x]) if(i!=fa) add(i,x,id,d+1);
}
void dfs2(int x,int fa)
{
for(int i:e[x]) if(i!=fa) calc(i,x,x,1),add(i,x,x,1);
for(int i:e[x]) if(i!=fa) dfs2(i,x);
}
void calc(int x)
{
for(int i=1; i<=n; ++i) c[i].clear();
dfs(x,x);
dfs2(x,x);
}
signed main()
{
init(n);
for(int i=1,p,q; i<n; ++i)
p=read(),q=read(),e[p].push_back(q),e[q].push_back(p);
for(int i=1; i<=n; ++i)
calc(i);
printf("%lld\n",s*qp(n,p-2)%p);
return 0;
}