「十二省联考 2019」希望

「十二省联考 2019」希望

传送门

Solution

毒瘤题令人。。。。

首先,如果直接计算每个点的贡献就会算重,考虑容斥

发现一个合法方案的合法点集是个联通子图,满足\(V(S)-E(S)=1\)

所以可以把点的贡献和减去边的贡献和

\(f(x)\)表示以\(x\)为中心的深度不超过\(L\)的联通块数量,\(g(<x,y>)\)表示以\(x,y\)为中心深度均不超过\(L\)的联通块数量

那么答案就是
\[ ans=\sum_{i\in V}f(i)^k-\sum_{i\in E}g(i)^k \]
根据如下定义
\[ f(i)=(dp_{i,L}+1)up_{i,L} \\ g(<x,fa_x>)=(dp_{x,L-1}+1)up_{fa_x,L-1} \]

\(update:\)

  • 所需要的可回退化数据结构需要维护两个部分
  1. 每个点以下的重链的全局标记以及后缀打上的赋值标记
  2. 每个点以下的重链上的单点修改标记,需要开一个stack/vector/list什么的

有一个细节,让我调到了凌晨\(2:30\),就是预处理逆元的时候,要忽视那些\(0\)的。。。。

Code

#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
#define dbg3(x) cerr<<#x<<"\n"
using namespace std;
#define reg register
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
const int P=998244353,N=1e6+5;
#define Mul(x,y) (1ll*(x)*(y)%P)
#define Add(x,y) ((x+y)%P)
int fp(int x,int y){int r=1;for(;y;y>>=1,x=Mul(x,x))if(y&1)r=Mul(r,x);return r;}
int n,L,K,ans,a[N][2];
struct ed{int to,nex;}e[N<<1];int en,hr[N];
inline void ins(int x,int y)
{
    e[++en]=(ed){y,hr[x]};hr[x]=en;
    e[++en]=(ed){x,hr[y]};hr[y]=en;
}
int inv[N],fa[N],len[N*3],son[N],f[N],fac[N],Prod;
void dfs1(int x,int F)
{
    len[x]=1;fa[x]=F;f[x]=1;
    for(int i=hr[x];i;i=e[i].nex)if(e[i].to^F)
    {
        dfs1(e[i].to,x);f[x]=Mul(f[x],f[e[i].to]);
        if(len[x]<len[e[i].to]+1) len[x]=len[e[i].to]+1,son[x]=e[i].to;
    }
    (++f[x])%=P;if(f[x])Prod=Mul(Prod,f[x]);
}
int id[N],dfn[N],dind;
void dfs2(int x)
{
    id[dfn[x]=++dind]=x;if(son[x])dfs2(son[x]);
    for(int i=hr[x];i;i=e[i].nex)
        if((e[i].to^fa[x])&&(e[i].to^son[x]))
            dfs2(e[i].to);
}
void init()
{
    reg int i;Prod=1;dfs1(1,0);dfs2(1);
    for(inv[n]=fp(Prod,P-2),i=n-1;i;--i)inv[i]=Mul(inv[i+1],max(f[i+1],1));
    for(fac[0]=i=1;i<=n;++i) fac[i]=Mul(fac[i-1],max(f[i],1));
    for(i=1;i<=n;++i) inv[i]=Mul(inv[i],fac[i-1]);
}
struct node{int a,b,inva,pos,val;};
struct DP{
    vector<pair<node,vector<pair<int,int> > > > _[N];
    node tag[N*3];int dp[N*3];
    int Val(int x,int y){int r=y<tag[x].pos?dp[x+y]:tag[x].val;return Add(Mul(r,tag[x].a),tag[x].b);}
    void Cal(int x,int y,int val){dp[x+y]=Mul(val+P-tag[x].b,tag[x].inva);}
    void Cb(int x,int y,int Ly)
    {
        int i,j;
        node ori=tag[x];vector<pair<int,int> >r;
        for(i=1;i<=Ly;++i)
        {
            r.pb(mp(i,dp[x+i]));
            if(i==tag[x].pos) dp[x+tag[x].pos++]=tag[x].val;
            Cal(x,i,Mul(Val(x,i),Val(y,i-1)));
        }
        if(Ly<L)
        {
            int v=f[id[y]];
            if(v)
            {
                r.pb(mp(0,dp[x]));for(i=0,j=inv[id[y]];i<=Ly;++i) Cal(x,i,Mul(Val(x,i),j));
                tag[x].a=Mul(tag[x].a,v);tag[x].b=Mul(tag[x].b,v);tag[x].inva=Mul(tag[x].inva,j);
            }
            else tag[x].pos=Ly+1,tag[x].val=P-Mul(tag[x].b,tag[x].inva);
        }
        if(x<=n)_[x].pb(mp(ori,r));
    }
    void dfs(int x)
    {
        if(son[id[x]])dfs(x+1),tag[x]=tag[x+1];
        else tag[x]=(node){1,1,1,n,0};Cal(x,0,1);
        for(int i=hr[id[x]];i;i=e[i].nex)
            if((e[i].to^son[id[x]])&&(e[i].to^fa[id[x]]))
                dfs(dfn[e[i].to]),Cb(x,dfn[e[i].to],min(len[e[i].to]-1,L));
        a[x][1]=Val(x,min(L,len[id[x]]-1)),a[x][0]=Val(x,min(L-1,len[id[x]]-1));(++tag[x].b)%=P;
    }
    void One_step(int x)
    {
        x=dfn[x];tag[x]=_[x].back().fi;
        #define xx (_[x].back().se)
        for(int i=xx.size()-1;~i;--i)dp[x+xx[i].fi]=xx[i].se;
        _[x].pop_back();
        #undef xx
    }
    void solve(){dfs(1);}
}_dp;
struct UP{
    node tag[N];int up[N*3],pos[N],pin,tt,p2[N];
    int Val(int x,int y){int r=y<tag[x].pos?up[pos[x]+y]:tag[x].val;return Add(Mul(r,tag[x].a),tag[x].b);}
    void Cal(int x,int y,int val){up[pos[x]+y]=Mul(val+P-tag[x].b,tag[x].inva);}
    void dfs(int x)
    {
        if(len[x]-L-1>=0) Cal(x,len[x]-L-1,1);
        a[dfn[x]][1]=Mul(a[dfn[x]][1],Val(x,len[x]-1));
        if(fa[x]) a[dfn[x]][0]=Mul(a[dfn[x]][0],Add(Val(x,len[x]-1),P-1));
        if(!son[x])return;vector<int> c;int v,mL=0,i;
        for(i=hr[x];i;i=e[i].nex)if((e[i].to^fa[x])&&(e[i].to^son[x]))c.pb(e[i].to),mL=max(mL,len[e[i].to]);mL=min(mL,L);
        reverse(c.begin(),c.end());p2[x]=tt;tt+=mL+1;
        _dp.tag[p2[x]]=(node){1,1,1,n,0};_dp.Cal(p2[x],0,1);
        for(int o=0;o<c.size();++o)
        {
            v=c[o];_dp.One_step(x);pos[v]=pin;pin+=len[v];
            for(i=max(len[v]-L-1,0);i<len[v];++i)
            {
                if(~(L-len[v]+i)) up[pos[v]+i]=Mul(Val(x,len[son[x]]-len[v]+i),
                    Mul(_dp.Val(dfn[x],min(len[x]-1,L-len[v]+i)),_dp.Val(p2[x],min(mL,L-len[v]+i))));
                else up[pos[v]+i]=Val(x,len[son[x]]-len[v]+i);
            }
            tag[v]=(node){1,1,1,n,0};_dp.Cb(p2[x],dfn[v],min(len[v]-1,L));dfs(v);
        }
        v=son[x];pos[v]=pos[x];tag[v]=tag[x];
        for(i=max(len[v]-L,0);i<=len[v]+mL-L-1;++i)
        {
            if(tag[v].pos==i) up[pos[v]+tag[v].pos++]=tag[v].val;
            Cal(v,i,Mul(Val(v,i),_dp.Val(p2[x],L-len[v]+i)));
        }
        if(mL<L)
        {
            int va=1,in=1;
            for(i=0;i<c.size();++i)va=Mul(va,f[c[i]]),in=Mul(in,inv[c[i]]);
            if(!va)tag[v].pos=len[v]+mL-L,tag[v].val=P-Mul(tag[v].b,tag[v].inva);
            else
            {
                for(i=max(len[v]-L-1,0);i<=len[v]+mL-L-1;++i)Cal(v,i,Mul(Val(v,i),in));
                tag[v].a=Mul(tag[v].a,va);tag[v].b=Mul(tag[v].b,va);tag[v].inva=Mul(tag[v].inva,in);;
            }
        }
        (++tag[v].b)%=P;dfs(v);
    }
    void solve()
    {
        pos[1]=1;tt=n+1;pin=1+len[1];tag[1]=(node){1,1,1,n,0};dfs(1);
        for(int i=1;i<=n;++i) ans=Add(ans,fp(a[i][1],K));
        for(int i=2;i<=n;++i) ans=Add(ans,P-fp(a[i][0],K));
    }
}_up;
int main()
{
    n=read();L=read();K=read();int i,j;
    for(i=1;i<n;++i) j=read(),ins(j,read());
    init();_dp.solve();_up.solve();
    return 0*printf("%d\n",ans);
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

猜你喜欢

转载自www.cnblogs.com/PaperCloud/p/11311034.html