2019牛客多校第二场B题(随机求概率)

题目链接:https://ac.nowcoder.com/acm/contest/882/A

题意:现在有一个长度为未知环,每次你可以向前或者向后走一步。现在有T个回合,每个回合给你两个整数n和m。现在问你,在第i个回合中,在满足第i−1个回合的条件的前提下,在该回合中,将长度为n的环上的所有的点都访问过至少一次并最终落在点m的可能性。

解析:
对于这类询问概率的问题,我们可以采用蒙特卡洛随机的方法进行随机分析(说白了也就是随机算法)。

我们可以模拟若干次题意的操作,并求解出大概的概率,根据归纳分析,我们发现,当m不等于0的情况下,答案与m的值无关,只与n的值有关且答案为1/n−1。因此我们只需要用快速幂求解逆元即可,注意上一次回合的答案会累积到本回合。时间复杂度O(nlogn)。

需要注意的是,在swindows系统下,随机函数rand()rand()在数据较大的情况可能会发生比较大的误差。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
int montekalo(int n)
{
    int cur=0,vis[10005],cnt=1;
    memset(vis,0,sizeof(vis));
    vis[0]=1;
    int tmp=0;
    while(cnt<n)
    {
        int x=rand()%szae;
        if(x)
        {
            cur=(cur+1)%n;
        }
        else cur=(cur-1+n)%n;
        if(!vis[cur])
        {
            vis[cur]=1;
            cnt++;
        }
    }
    return cur;
}
void gen(int n,int m)
{
    int cnt=0,res=0;
    while(cnt<=100000)
    {
        if(montekalo(n)==m) res++;
        cnt++;
    }
    printf("%d %d %.5f\n",res,cnt,1.0*res/cnt);
}
int main()
{

    while(~scanf("%d%d",&n,&m))
    {
        gen(n,m);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值