loj 2542 随机游走 —— 最值反演+树上期望DP+fmt
生活随笔
收集整理的这篇文章主要介绍了
loj 2542 随机游走 —— 最值反演+树上期望DP+fmt
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
题目:https://loj.ac/problem/2542
因为走到所有点的期望就是所有点期望的最大值,所以先最值反演一下,问题变成从根走到一个点集任意一点就停止的期望值;
设 \( f[x] \),则 \( f[x] = \frac{f[fa]+1+\sum\limits_{v \in son} (f[v]+1)}{d[x]} \),其中 \( d[x] \) 是 \( x \) 的度数;
因为其实只和 \( fa \) 有关,所以套路是设 \( f[x] = K[x] * f[fa] + B[x] \),推一推就可以树形DP求 \( K[x] , B[x] \),这好像叫“树上高斯消元”?!
因为走到集合内任意一个点就停止,所以 \( K[x] = B[x] = 0 ( x \in S ) \),\( f[rt] \) 即 \( B[rt] \) 就是答案;
然后高维前缀和求子集的 \( f \) 和,注意最值反演的符号要一开始就带上。
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int rd() {int ret=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();return f?ret:-ret; } int const xn=20,xm=(1<<18)+5,mod=998244353; int n,rt,sid[xn][xn],bin[xn],cnt[xm],K[xn],B[xn],d[xn],f[xm]; ll pw(ll a,int b){a%=mod; ll ret=1; for(;b;b>>=1,a=a*a%mod)if(b&1)ret=ret*a%mod; return ret;} int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;} void dfs(int x,int fa,int s) {if(s&bin[x-1]){K[x]=B[x]=0; return;}int ks=0,bs=0;for(int u=1;u<=n;u++)if(sid[x][u]&&u!=fa)dfs(u,x,s),ks=upt(ks+K[u]),bs=upt(bs+B[u]);K[x]=pw(d[x]-ks,mod-2); B[x]=(ll)(bs+d[x])*pw(d[x]-ks,mod-2)%mod; } int main() {n=rd(); int Q=rd(); rt=rd();for(int i=1,x,y;i<n;i++)x=rd(),y=rd(),sid[x][y]=sid[y][x]=1,d[x]++,d[y]++;bin[0]=1; for(int i=1;i<=n;i++)bin[i]=(bin[i-1]<<1);for(int s=1;s<bin[n];s++)cnt[s]=cnt[s>>1]+(s&1);for(int s=1;s<bin[n];s++){memset(K,0,sizeof K); memset(B,0,sizeof B);dfs(rt,0,s); f[s]=upt(((cnt[s]&1)?1:-1)*B[rt]);// }for(int i=1;i<=n;i++)for(int s=0;s<bin[n];s++)if(s&bin[i-1])f[s]=upt(f[s]+f[s^bin[i-1]]);for(int i=1,k,s;i<=Q;i++){k=rd(); s=0;for(int j=1,x;j<=k;j++)x=rd(),s|=bin[x-1];printf("%d\n",f[s]);}return 0; }
转载于:https://www.cnblogs.com/Zinn/p/10279681.html
总结
以上是生活随笔为你收集整理的loj 2542 随机游走 —— 最值反演+树上期望DP+fmt的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Struts2拦截SQL注入
- 下一篇: oracle数据表管理