模拟赛T2 仙人掌毒题




分析:
我们首先知道这样一个公式:
对于树:连通块=点-边
对于仙人掌:连通块=点-边+环
考虑期望的线性性:
连通块期望=点期望-边期望+环期望

对于点:
一个点T次标记后还为0的概率为\((\frac{n-1}{n})^T\),为1就是\(1-(\frac{n-1}{n})^T\)
乘上系数n就是点期望

对于边:
一条边两边点都是0的概率为\((\frac{n-2}{n})^T\)
为1要容斥一下,概率为\(1-2(\frac{n-1}{n})^T+(\frac{n-2}{n})^T\)

然后就是重头戏
我们要维护仙人掌并讨论环:
一个大小为m的环中所有点为0的概率为\((\frac{n-m}{n})^T\)
为1的概率要进行容斥:
\(ans=\sum_{i=0}^{m}(-1)^iC_{m}^{i}(\frac{n-i}{n})^T\)
没必要什么花里胡哨NTT,暴力O(m)算平摊下来复杂度也只有O(n),因为每条边只会存在于一个环中

然后就是维护仙人掌
喜 闻 乐 见的LCT维护圆方树
每次看链上的边是否已被一条额外边覆盖就好了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<queue>

#define maxn 200005
#define INF 0x3f3f3f3f
#define MOD 998244353

using namespace std;

inline long long getint()
{
    long long num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    return num*flag;
}

long long n,m,T,W,tot,invn;
long long fac[maxn],inv[maxn];
int sum[maxn],ch[maxn][2],fa[maxn],rev[maxn],stag[maxn],tag[maxn];
int stk[maxn],tp;
long long P,E,Cir;
int Q[maxn],sz;

inline long long C(long long p,long long q)
{return fac[p]*inv[q]%MOD*inv[p-q]%MOD;}

inline long long ksm(long long num,long long k)
{
    long long ret=1;
    for(;k;k>>=1,num=num*num%MOD)if(k&1)ret=ret*num%MOD;
    return ret;
}

inline bool isroot(int x)
{return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}

inline void pushup(int x)
{stag[x]=stag[ch[x][0]]|stag[ch[x][1]]|tag[x];}

inline void rv(int x)
{rev[x]^=1,swap(ch[x][0],ch[x][1]);}

inline void pushdown(int x)
{if(rev[x])rev[x]=0,rv(ch[x][0]),rv(ch[x][1]);}

inline void rotate(int x)
{
    int y=fa[x],z=(ch[fa[x]][1]==x);
    ch[y][z]=ch[x][z^1];
    if(ch[x][z^1])fa[ch[x][z^1]]=y;
    if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
    fa[x]=fa[y];
    fa[y]=x;
    ch[x][z^1]=y;
    pushup(y);
}

inline void splay(int x)
{
    int tmp=x;
    while(!isroot(tmp))stk[++tp]=tmp,tmp=fa[tmp];
    stk[++tp]=tmp;
    while(tp)pushdown(stk[tp--]);
    while(!isroot(x))
    {
        if(!isroot(fa[x]))
        {
            if((ch[fa[x]][1]==x)==(ch[fa[fa[x]]][1]==fa[x]))rotate(fa[x]);
            else rotate(x);
        }
        rotate(x);
    }
}

inline void access(int x)
{for(int u=0;x;u=x,x=fa[x])splay(x),ch[x][1]=u,pushup(x);}

inline void makeroot(int x){access(x),splay(x),rv(x);}

inline void link(int x,int y)
{makeroot(x),access(x),splay(x),fa[x]=y;}

inline void cut(int x, int y)
{
    makeroot(x),access(y),splay(y);
    ch[y][0]=0,fa[x]=0,pushup(y);
}

inline bool check(int x,int y)
{
    makeroot(x),splay(x),access(y),splay(y);
    return !isroot(x);
}

inline void solve(int x)
{
    if(!x)return;
    pushdown(x);
    solve(ch[x][0]),Q[++sz]=x,solve(ch[x][1]);
}

inline long long calc(int sz)
{
    long long ret=0;
    for(int i=0;i<=sz;i++)
        (ret+=((i&1)?MOD-1:1)*C(sz,i)%MOD*ksm((n-i)*invn%MOD,T))%=MOD;
    return ret;
}

int main()
{
    n=getint(),m=getint(),T=getint(),W=getint();
    fac[0]=fac[1]=inv[0]=inv[1]=1;
    for(int i=2;i<maxn;i++)fac[i]=fac[i-1]*i%MOD;
    for(int i=2;i<maxn;i++)inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
    for(int i=2;i<maxn;i++)inv[i]=inv[i]*inv[i-1]%MOD;
    invn=ksm(n,MOD-2),tot=n;
    P=W?n:n*ksm((n-1)*invn%MOD,T)%MOD;
    while(m--)
    {
        int u=getint(),v=getint();
        int p=0;
        if(check(u,v))
        {
            makeroot(u),access(v),splay(v);
            if(!stag[v])
            {
                sz=0;solve(v);
                (Cir+=ksm((n-sz)*invn%MOD,T))%=MOD;
                if(W)(Cir+=calc(sz))%=MOD;
                tot++;
                tag[tot]=1;
                pushup(tot);
                for(int i=1;i<sz;i++)cut(Q[i],Q[i+1]),link(Q[i],tot);
                link(Q[sz],tot);
            }
            else p=1;
        }
        else link(u,v);
        if(!p)
        {
            (E+=ksm((n-2)*invn%MOD,T))%=MOD;
            if(W)(E+=1-2*ksm((n-1)*invn%MOD,T)%MOD+ksm((n-2)*invn%MOD,T)+MOD)%=MOD;
        }
        printf("%lld\n",(P-E+Cir+MOD)%MOD);
    }
}

原文地址:https://www.cnblogs.com/Darknesses/p/12309598.html

时间: 2024-10-20 16:16:14

模拟赛T2 仙人掌毒题的相关文章

2017 9 11 noip模拟赛T2

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=205; int map[N][N]; int d[N],tag[N],book[N],f[N]; int n,m; void work(int x) { memset(d,63,sizeof(d)); memset(book,0,sizeof(book)); memset(f,0,sizeof(

jzoj5987. 【WC2019模拟2019.1.4】仙人掌毒题 (树链剖分+概率期望+容斥)

题面 题解 又一道全场切的题目我连题目都没看懂--细节真多-- 先考虑怎么维护仙人掌.在线可以用LCT,或者像我代码里先离线,并按时间求出一棵最小生成树(或者一个森林),然后树链剖分.如果一条边不是生成树上的边,它肯定会和树上\(u,v\)这条路径构成一个环,然后对于每条树边记录一下这条树边被覆盖过没有.如果\(u,v\)路径上有任何一条树边被覆盖过,那么就说明路径上有一条边已经在一个简单环中,这条非树边就不能加.否则就加上这条边并让这条路径上所有树边的覆盖次数加一 然后考虑期望连通块个数.首先

liu_runda 给辣鸡蒟蒻做的 NOIP模拟赛 1.0 第二题 任(duty) 题解

问题 B: 任(duty) 时间限制: 2 Sec  内存限制: 512 MB 题目描述 liu_runda退役之后就失去梦想开始咸鱼生活了- Bilibili夏日画板活动中,所有人都可以在一块画板上进行像素画创作.UOJ群有一群无聊的人决定在画板上创作一个50*50的UOJ的LOGO.如下图. 这块画板实际上是很大的矩形网格.一个网格是一像素. 一个人每三分钟才能画一个像素.所以liu_runda的咸鱼生活非常无聊. 郭神表示他实在是看不下去liu_rudna这只颓狗了,于是随手出了一道神题,

2017 9 27 模拟赛 T2

原题题意:给出一个集合S,现满足以下关系: 实际题意:求32的n次方(这...)

2018.02.12 noip模拟赛T2(未完待续)

二兵的赌注 Description游戏中,二兵要进入了一家奇怪的赌场.赌场中有n个庄家,每个庄家都可以猜大猜小,猜一次一元钱.每一次开彩前,你都可以到任意个庄家那里下赌注.如果开彩结果是大,你就可以得到你之前猜大的庄家相应的ai元钱.如果开彩结果是小,你就可以得到你之前猜小的庄家相应的bi元钱.你可以在同一个庄家那里既猜大又猜小,(这样是两块钱),也可以什么都不猜(这样不用钱).问怎么样下注,才能赢得最多的有保障的钱.有保障的钱指不管开彩结果是大是小,你都能够赢得相应的钱.你能帮助他计算这个值吗

[模拟赛] T2 不等数列

Description 将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入">"和"<".问在所有排列中,有多少个排列恰好有k个"<".答案对2015取模. 注:1~n的排列指的是1~n这n个数各出现且仅出现一次的数列. Input 第一行2个整数n,k. Output 一个整数表示答案. Range 对于30%的数据:n <= 10 对于100%的数据:k < n <= 1000 Solutio

20180523模拟赛T2——前缀!

简化版题面 jyt毒瘤,写了超长的题面,要看完整题面的翻到最后-- 定义\(f_0(x) = A_x\),\(f_n(x) = \sum^x_{i = 1} f_{n-1}(i)\).给出长度为\(N\)的数组\(A\)(从\(1\)~\(n\)编号)和\(Q\)个操作.操作有两种:Add i j 表示将\(A_i\)的值加上\(j(j\le P)\):Query i j表示询问\(f_i(j)\)的值\((1\le M)\),由于答案可能会很大,给我 mod P 后的答案即可,\(P=1,00

20180530模拟赛T2——绀碧之棺

题目背景Background qiancl 得到了一张藏宝图,上面写了一道谜题. 题目描述 Description 定义\(F(n)\)为 n 在十进制下各个数位的平方和,求区间\([a,b]\)中有多少\(n\)满足\(k\times F(n) = n\). 输入描述 (coffin.in) Input Description 一行三个正整数\(k,a,b\). 输出描述 (coffin.out) Output Description 一行一个整数表示满足条件的\(n\)的个数. 样例输入Sa

20180706模拟赛T2——染色

文件名: seq 题目类型: 传统题 时间限制: 1秒 内存限制: 128MB 编译优化: 无 题目描述 小A正在帮助小M刷她家的墙壁 小M家的墙可以分为\(n\)块,每段需要被刷成黑色或者白色.你可以认为每一块墙最开始时既不是黑色也不是白色. 小M有一把神奇的刷子,每次可以刷连续的一段墙,但先刷的颜色会被后刷的颜色覆盖.这把刷子只能够用\(k\)次 现在小A想要知道,最多能正确地刷对多少块墙的颜色. 输入格式 第一行两个正整数\(n,k\) 接下来\(n\)个整数,每个整数都是0或者1表示这块