抽卡毕业概率(转盘式)
模拟的是卡池上新,毕业指所有新卡至少抽到一张。
因为只在乎抽新卡,所以做成转盘式,只考虑随机数落到了特定小区间内,落在外面一律忽略就行。
其它抽卡模型:共享卡池、卡表、稀有度分层
相关机制:水位、保底、氪度
/*
文件名:random.cpp
作者:SXBKDpiang
描述:模拟抽卡
修改时间:2020.08.13
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;
//基于大数定律,以多次实验排除偶然误差,计算卡池毕业的概率
struct Card //每个结构体表示一张新卡,左右区间可以想象成转盘抽奖,随机到区间里表示抽到了
{
int left; //左区间
int right; //右区间
int flag=0; //该卡是否被抽到,0表示没有,1表示抽到
};
int main()
{
const int ExperimentTimes=20000; //实验次数,即人数
const int Lowest=0.1; //概率最小的卡的概率,一般都是0.1的倍数吧
const int Total=1000; //放大后的总区间,100/Lowest
int PresentNumber=0; //记录生成的随机数
int graduate[ExperimentTimes]={0}; //c[i]记录一共用了i抽毕业的人数
srand((unsigned)time(NULL)); //随机数
/*
设计判定条件
*/
int CardNumber=0; //新卡数量
cout<<"请输入本次要抽的卡的数量:";
cin>>CardNumber;
struct Card card[CardNumber]; //C99后可以这么开数组了
cout<<"请输入各个卡的概率:";
int number=0; //划分每张卡的判定范围
for(int i=0;i<CardNumber;i++) //第一张卡的区间是0-np,意为随机到这个区间时是抽到了第一张卡
{
float p; //每张卡的概率
cin>>p;
card[i].left=number;
number=number+p*2; //同比例放大到整数
card[i].right=number;
number++;
}
for(int z=0;z<ExperimentTimes;z++) //多次实验找到普遍规律
{
//换人时重置flag
for(int i=0;i<CardNumber;i++)
card[i].flag=0;
for(int i=1;i<=100*Total;i++) //保证单人抽卡足够多,一定能毕业,只是10连或是1000连的区别
{
PresentNumber = rand()%Total; //这一次抽到了第PresentNumber张卡
for(int n=0;n<CardNumber;n++)
if(card[n].left<=PresentNumber&&card[n].right>=PresentNumber)
card[n].flag=1;
//判断是否毕业
int Count=0;
for(int n=0;n<CardNumber;n++)
{
if(card[n].flag==1)
Count++;
}
if(Count==CardNumber)
{
graduate[i]++; //第m个人为i抽毕业
break; //毕业了就换下一个人
}
}
}
for(int i=0;i<200;i++)
{
for(int j=0;j<10;j++)
{
cout<<10*i+j<<":"<<graduate[10*i+j]<<" ";
}
cout<<endl;
}
/*
根据给定的预计排位(0-1)计算对应的抽卡数
*/
float percent; //比多少人非,0~1
float C=0; //C=i抽内毕业人数
cout<<"比多少人非0-1"<<endl;
cin>>percent;
//percent=percent*ExperimentTimes; //比你欧的人数
//最欧的人抽了Search次
int Search=0;
while(graduate[Search]==0)
Search++;
for(int i=Search;i<ExperimentTimes;i++)
{
if(C/ExperimentTimes<percent)
C+=graduate[i]; //C=i抽内毕业人数
else
{
cout<<i<<"抽"<<endl;
break;
}
}
/*
根据给的抽卡次数计算毕业概率
*/
int DrawTimes;
float Percent=0;
cout<<"多少抽毕业"<<endl;
cin>>DrawTimes;
for(int i=0;i<DrawTimes;i++)
Percent=Percent+graduate[i];
cout<<Percent/ExperimentTimes<<endl;
return 0;
}