zoukankan      html  css  js  c++  java
  • LOJ2542. 「PKUWC2018」随机游走

    LOJ2542. 「PKUWC2018」随机游走

    https://loj.ac/problem/2542

    分析:

    • 为了学习最值反演而做的这道题~
      • (max{S}=sumlimits_{Tsubseteq S}(-1)^{|T|-1}min{T})
        考虑排序后的(a)序列。
    • (sumlimits_{Tsubseteq S}(-1)^{|T|-1}min{T}=sumlimits_{i=1}^na_isumlimits_{j=0}^{n-i}(-1)^jinom{n-i}{j})
    • (sumlimits_{Tsubseteq S}(-1)^{|T|-1}min{T}=sumlimits_{i=1}^na_i[n-i=0])
    • (sumlimits_{Tsubseteq S}(-1)^{|T|-1}min{T}=a_n=max{S})
    • (f_{s,i})表示(f)第一次走到(s)状态的期望步数。
    • 这个东西我们直接枚举(s)然后树上高斯消元即可。
    • 最后再(fwt)一下就能得到反演后的(min_s)了。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    using namespace std;
    #define mod 998244353
    typedef long long ll;
    #define N 20
    #define M ((1<<18)+50)
    int n,head[N],to[N<<1],nxt[N<<1],du[N],rt,m;
    int S,Cnt[M],cnt;
    inline void add(int u,int v) {to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;}
    ll K[N],B[N],inv[N],f[M];
    ll qp(ll x,ll y) {
    	ll re=1;
    	for(;y;y>>=1,x=x*x%mod)if(y&1)re=re*x%mod;return re;
    }
    void dfs(int x,int y) {
    	int i;
    	if(S&(1<<(x-1))) {K[x]=B[x]=0; return ;}
    	K[x]=inv[du[x]]; B[x]=1; ll lhs=1;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
    		dfs(to[i],x);
    		lhs=(lhs-K[to[i]]*inv[du[x]])%mod;
    		B[x]=(B[x]+B[to[i]]*inv[du[x]])%mod;
    	}
    	lhs=qp(lhs,mod-2);
    	K[x]=K[x]*lhs%mod; B[x]=B[x]*lhs%mod;
    }
    void fwt(ll *a,int len) {
    	int i,j,k,t;
    	for(k=2;k<=len;k<<=1) for(t=k>>1,i=0;i<len;i+=k) for(j=i;j<i+t;j++) a[j+t]=(a[j+t]+a[j])%mod;
    }
    int main() {
    	scanf("%d%d%d",&n,&m,&rt);
    	int i,x,y;
    	for(i=1;i<n;i++) {
    		scanf("%d%d",&x,&y); add(x,y); add(y,x); du[x]++; du[y]++;
    	}
    	for(i=1;i<=n;i++) inv[i]=qp(i,mod-2);
    	int mask=(1<<n)-1;
    	for(i=0;i<=mask;i++) {
    		S=i;
    		dfs(rt,0);
    		Cnt[i]=Cnt[i>>1]+(i&1);
    		f[i]=B[rt];
    		if(!(Cnt[i]&1)) f[i]=-f[i];
    	}
    	fwt(f,(1<<n));
    	while(m--) {
    		int k,s=0;
    		scanf("%d",&k);
    		while(k--) {
    			scanf("%d",&x); s|=(1<<(x-1));
    		}
    		printf("%lld
    ",(f[s]+mod)%mod);
    	}
    }
    
  • 相关阅读:
    SQL 初级教程学习(二)
    QuartzJobs 如何发布服务
    Net 发布网站中遇到的几点问题
    PWBI--Excel 数据源
    微信小程序资源
    加密和解密之非对称加密
    Js 使用小技巧总结(1)
    路径的读取
    json和Jsonp 使用总结(3)
    json和Jsonp 使用总结(2)
  • 原文地址:https://www.cnblogs.com/suika/p/10205172.html
Copyright © 2011-2022 走看看