1 条题解
-
2
直接按题意模拟是很难做的,因此考虑对每条边统计其被经过的期望次数。
不妨设 为根,假设一条边从 到 ( 深度大于 ),那么发现仅在进出以 为根的子树时这条边被经过,而子树内的特殊点数容易统计。
因此,对于每条边,问题可转化为有 个带标号的 和 个带标号的 ,将其任意排列组成一个长为 的序列,求期望形成的极大相同子段数减一(e.g.:0011110010 有 5 个极大相同子段,边被经过 4 次;0000000000 有 1 个极大相同子段,边没有被经过)。
对于 设这个值为 ,考虑对这个值进行推导。首先我们枚举极大相同子段数设为 ,那么发现存在两种情况:序列以 起始,有 个全是 的极大相同子段和 个全是 的极大相同子段;或者相反。这个对于 和 就可以分别等效求 的正整数解个数。设 ,插板法得
$f_x=\sum_{j=1}^{m}(j-1)\Big (\binom{x-1}{t-1}\binom{m-x-1}{j-t-1}+\binom{x-1}{j-t-1}\binom{m-x-1}{t-1}\Big)$
做出这步计数相当于把长为 的 序列确定下来。但发现带标号的 和 、 和 之间可以任意交换,且求的是期望所以要除以总排列数,所以上面的式子还需要加个系数,实际
$f_x=\frac{x!(m-x)!\sum_{j=1}^{m}(j-1)\Big (\binom{x-1}{t-1}\binom{m-x-1}{j-t-1}+\binom{x-1}{j-t-1}\binom{m-x-1}{t-1}\Big)}{m!}$
即
$f_x=\frac{\sum_{j=1}^{m}(j-1)\Big(\binom{x-1}{t-1}\binom{m-x-1}{j-t-1}+\binom{x-1}{j-t-1}\binom{m-x-1}{t-1}\Big)}{\binom{m}{x}}$
然后你可以开始打表找规律了发现分母很简洁,所以把分子设为 ,考虑化简分子,公式不再重复了。
首先 的形式不易化简,所以我们考虑把枚举 改为枚举 ,对 和 求值。公式变为
$h_x=\sum_{t=0}^{\left \lfloor \frac{m}{2} \right \rfloor}(2t-1)\Big(\binom{x-1}{t-1}\binom{m-x-1}{t-1}+\binom{x-1}{t-1}\binom{m-x-1}{t-1}\Big)+2t\Big(\binom{x-1}{t-1}\binom{m-x-1}{t}+\binom{x-1}{t}\binom{m-x-1}{t-1}\Big)$
然后这个式子的形式就比较好看了。根据 的定义可以把 和 下面的 都化成 ,然后在前面乘上对应系数。化简得到
$h_x=\sum_{t=0}^{\left \lfloor \frac{m}{2} \right \rfloor}(2m-2)\binom{x-1}{t-1}\binom{m-x-1}{t-1}$
这时发现 是一个常数,所以提出 并由范德蒙德卷积得
场上打表半小时可以直接观察出来然后 也就求出来了。
统计初始答案时就用每条边的这个值乘上边权然后求和,而每条边的这个值是固定的所以也容易统计每个点相邻的边的这个值的和,设为 。修改 时答案增加 即可。总复杂度 。
贴一个代码
#include<bits/stdc++.h> #define uint unsigned int #define ll long long #define ull unsigned long long #define PII pair<int,int> #define PLL pair<ll,ll> #define DU double #define rep(i,x,n) for(int i=(x);i<=(n);i++) #define nep(i,x,n) for(int i=(x);i>=(n);i--) using namespace std; const int N=5e5+10,M=1e6+10,mod=998244353; int n,m,q,rt=1,h[N],e[M],ne[M],w[M],idx; int res,siz[N],fct[N],infct[N],inv[N],f[N],g[N]; inline int read(){ int s=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return s*f; } inline void print(int x){ if(x<0){ putchar('-'); x=-x; } if(x>9) print(x/10); putchar(x%10+'0'); } inline int addmod(int x,int y){ return x+y>=mod?x+y-mod:x+y; } inline int submod(int x,int y){ return x-y<0?x-y+mod:x-y; } inline int C(int x,int y){ if(x<y) return 0; if(x<0||y<0) return 1; return (ll)fct[x]*infct[y]%mod*infct[x-y]%mod; } inline void add(int a,int b,int c){ e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++; } inline void dfs1(int u,int fa){ for(int i=h[u];~i;i=ne[i]){ int v=e[i];if(v==fa) continue; dfs1(v,u);siz[u]+=siz[v]; g[u]=addmod(g[u],f[siz[v]]); g[v]=addmod(g[v],f[siz[v]]); res=addmod(res,(ll)f[siz[v]]*w[i]%mod); } } inline void Solve(){ n=read(),m=read(); inv[1]=1;rep(i,2,n) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; fct[0]=1;rep(i,1,n) fct[i]=(ll)fct[i-1]*i%mod; infct[0]=1;rep(i,1,n) infct[i]=(ll)infct[i-1]*inv[i]%mod; rep(i,1,m-1){ f[i]=(ll)submod(addmod(m,m),2)*C(m-2,i-1)%mod*fct[i]%mod*fct[m-i]%mod*infct[m]%mod; } memset(h,-1,sizeof h); rep(i,1,n-1){ int x=read(),y=read(),z=read(); add(x,y,z),add(y,x,z); } rep(i,1,m){int x=read();siz[x]++;} dfs1(rt,0); q=read(); rep(i,1,q){ int x=read(),k=read(); res=addmod(res,(ll)g[x]*k%mod);print(res),puts(""); } } int main(){ // freopen("sakuya3.in","r",stdin); // freopen("sakuya.out","w",stdout); int Tests=1; while(Tests--) Solve(); return 0; }
- 1
信息
- ID
- 167
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 29
- 已通过
- 2
- 上传者