概率与期望

本文探讨了离散对数问题的解决方法,如BSGS算法及其应用,并讲解了原根的概念。此外,还讨论了几道涉及概率、期望及图论的题目,包括染色期望、生物繁殖概率等问题。

BSGS

1

题意:给定 a,b,pa,b,pax=b (mod p)ax=b (mod p) 的最小正整数解,pp 为质数,保证有解。

显然 x<p。令 t=pt=p, 如果我们能找到一组 (c,d) ,0<=d<t(c,d) ,0<=d<t ,使得:

(at)c=bad(at)c=b·ad

那么 xx 就等于 c·td
我们把 bai(0<=i<t)b·ai(0<=i<t) 放在一个哈希表里,然后枚举 cc,在表里找。
复杂度 O(n)

原根

(a,m)=1(a,m)=1 满足 ar=1 (mod m)ar=1 (mod m) 的最小正整数解称作 aam 的阶。
如果整数 aam 的阶为 ϕ(m)ϕ(m) 那么称 aa 是模 m 的原根。
计算原根:由于原根一般不会很大,我们可以枚举原根 aa,判断 a 的阶是不是 ϕ(n)ϕ(n)

推论:原根 gg0,1,,ϕ(p) 次方构成模 pp 的一个缩系。

2

题意:给定 p,k,app 是质数),求所有满足 xk=a (mod p)xx

gpp 的原根,则 x 可以表示为: gzgzaa 可以表示为 gb:

xzk=gb (mod p)xzk=gb (mod p)

两边同取离散对数:
zk=b (mod p1)z·k=b (mod p−1)

解线性同余方程。

概率与期望

条件概率:P(B|A)=P(AB)P(B)P(B|A)=P(A⋂B)P(B)
无论两随机变量是否独立,期望的线性性始终成立。

3

题意:nn 个点的有根树,每个点是白色的,每次等概率选择一个点染黑,并且把它子树里的点都染黑。求把整颗树染黑的期望次数。

貌似不是很好做…
换个角度,整颗树染黑以后,每个点被选中的概率。
一个点被染黑,当且仅当它的一个祖先或他自己被染黑。并且他们是等概率的。
由于选中代价是1,所以期望就是概率。
因此答案为:

i1deep[i]

4

题意:给定 nn 种物品,每次购买会随机买到一种,询问买到 n 种物品的期望次数。

考虑我们已经买到了 kk 种物品,再继续买多少次能得到第 k+1 种物品。
设它为 xx,则:

x=(1k/n)·(x+1)+k/n·1

整理得:

x=1(1k/n)x=1(1−k/n)

那么答案就是 nni=11nn∑i=1n1n

如果某件事发生的概率为 pp,那么发生这件事的期望次数是 1p

5

POJ[2069]
题意:一个软件有 ss 个子系统,会产生 n 种bug。某人每天发现一个bug,每个bug属于某个子系统的概率是 1/s1/s ,属于某种分类的概率是 1/n1/n 。问发现 nn 种bug,且每个子系统都发现bug的天数的期望。

f[i][j] 表示已经找到了 ii 种分类,j 种bug,还需要的期望天数。

f[i][j]=f[i][j+1]insjs+f[i+1][j]ninjs+f[i+1][j+1]ninsjs+f[i][j]injs+1f[i][j]=f[i][j+1]·in·s−js+f[i+1][j]·n−in·js+f[i+1][j+1]·n−in·s−js+f[i][j]·in·js+1

6

题意:初始有 kk 只生物,这种生物只能活一天,死的时候有 pi 的概率产生 ii 只新生物(也只能活一天),询问 m 天后所有生物都死的概率(包括 mm 天前死的情况)。

首先观察到每只生物是独立的,所以我们可以分开计算,最后 k 次方。
f[i]f[i] 表示 ii 天后所有生物都死的概率。转移的时候枚举第一天它产了几个子:

f[i]=j=0n1f[i1]j·pj

答案是 f[m]kf[m]k

7

BZOJ[1419]
题意:有 nn+1mm1,可以中途停止拿牌,询问按照最优策略拿牌,最后的得分期望。

f[i][j]f[i][j] 表示还有 ii+1jj1的得分期望。显然满足最优子结构性质。转移的时候如果期望小于 00 就不拿了。

f[i][j]=max(0,(f[i][j1]1)·ji+j+(f[i1][j]+1)·ii+j)

8

题意:要求摆放 nn 块骨牌,但排放时会有 pl 的概率使它左边所有挨着它的骨牌倒下,同理,右边的概率为 prpr,询问摆完 nn 块的期望次数。

f[i] 表示摆放连续 ii 个骨牌的期望次数。
转移的时候枚举 i 这个骨牌放在哪里。如果设摆好左边的期望次数为 E1E1 ,右边为 E2E2
f[i]f[i] 就等于期望往左边倒的次数×E1+×E1+期望往右边倒的次数×E2+×E2+不倒的期望次数+E1+E2+E1+E2
根据前面讲的,不倒的期望次数就是不倒的概率的倒数 11plpr11−pl−pr。也就是说,前面的 11plpr1=pl+pr1plpr11−pl−pr−1=pl+pr1−pl−pr 次都是往左或者往右倒的(很玄妙)。
那么,往左倒的期望次数就是 pl+pr1plprplpl+pr=pl1plprpl+pr1−pl−pr∗plpl+pr=pl1−pl−pr,右边同理。
因此,我们可以得到:

f[i]=pl1plprE1+pr1plprE2+11plpr+E1+E2f[i]=pl1−pl−pr·E1+pr1−pl−pr·E2+11−pl−pr+E1+E2

9

[NOI2015]聪聪和可可
题意:给定无向图,两个点A,B,每次A都向着离B最近的方向走,如果两个点都可以,走编号小的那个。A如果走一次没有遇到,可以接着再走一次。B每次等概率地走到相邻的点或待在原地,求A遇上B的期望时间。

f[i][j]f[i][j] 表示A在 ii,B在 j 的答案。

f[i][j]=1+(j,k)E|k=jf[pos(i,j)][k]d[j]+1f[i][j]=1+∑(j,k)∈E|k=jf[pos(i,j)][k]d[j]+1

pos(i,j)pos(i,j) 表示A在 ii,B在 j,下一步A的位置。因此我们需要预处理最短路,预处理 pospos,然后一波记忆化搜索。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#define ll long long
using namespace std;
struct edge{
    int to,next;
}ed[1000010];
double f[1100][1100];
int du[1100],dis[1100][1100],path[1100][1100],head[1100],sz,vis[1100][1100];
inline void add(int from,int to)
{
    ed[++sz].to=to;
    ed[sz].next=head[from];
    head[from]=sz;
}
inline void read(int &x)
{
    char c=getchar();x=0;int flag=1;
    while(!isdigit(c))
    {
        if(c=='-') flag=-1;
        c=getchar();
    }
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
    x*=flag;
}
double dfs(int A,int B)
{
    if(f[A][B]!=-1) return f[A][B];
    if(A==B) return f[A][B]=0;
    if(path[A][B]==B||path[path[A][B]][B]==B) return f[A][B]=1;
    f[A][B]=0;
    int pos=path[path[A][B]][B];
    for(int i=head[B];i;i=ed[i].next)
    {
        int v=ed[i].to;
        f[A][B]+=dfs(pos,v);
    }
    f[A][B]+=dfs(pos,B);
    f[A][B]/=(1.0*(du[B]+1));
    f[A][B]+=1;
    return f[A][B];
}
inline void dij(int s)
{
    queue <int> q;
    q.push(s);
    vis[s][s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=ed[i].next)
        {
            int v=ed[i].to;
            if(!vis[s][v])
            {
                dis[s][v]=dis[s][u]+1;
                vis[s][v]=1;
                q.push(v);
            }
        }
    }
}
int main()
{
    int n,m,A,B;
    read(n),read(m),read(A),read(B);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        read(u),read(v);
        add(u,v),add(v,u);
        du[u]++,du[v]++;
    }
    for(int i=1;i<=n;i++) dij(i);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j) continue;
            int ind=0,Min=1e9;
            for(int k=head[i];k;k=ed[k].next)
            {
                int v=ed[k].to;
                if(dis[v][j]<Min||(dis[v][j]==Min&&v<ind))
                {
                    Min=dis[v][j];
                    ind=v;
                }
            }
            path[i][j]=ind;
        }
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=-1;
    printf("%.3lf",dfs(A,B));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值