链接:https://ac.nowcoder.com/acm/contest/1085/H
来源:牛客网
题目描述
小sun非常喜欢玩游戏,最近他和同学正在玩这样一个游戏:
小sun有一个神奇的袋子,袋子里面有C种颜色的球,每种颜色的球都有无限多个。现在小sun每次将会从袋子里拿出一个球,然后将这个球放在桌面上,如果桌面上已经有这种颜色的球了,小孙就把它们两个重新放进袋子里。
在玩的时候小sun想到了一个问题,他想问问你:在第n次拿球后,桌上有m种颜色的球的概率是多少?
输入描述:
输入一行:c,n,m代表的含义如题中所述。
输出描述:
输出一行答案,保留3位小数
备注:
数据范围:
m≤c≤100
n≤1e12
n≤1e12
可一看到n很大,所以你要减小n,但是不能改变n的奇偶性(这个原理我也不知道,以后见到这样的可以减小到1e5或者1e4)
一维的写法:
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=2e5+100; double dp[1000]; double dp1[1000]; ll c,n,m; int main(){ cin>>c>>n>>m; if(n>2e5) n=2e5+n%2; dp[0]=1.0; for(int i=1;i<=n;i++){ for(int j=0;j<=c;++j){ if(j) dp1[j-1]+=dp[j]*((j*1.0)/(c*1.0)); if(j!=c) dp1[j+1]+=dp[j]*((c-j)*1.0)/(c*1.0); } for(int j=0;j<=c;j++){ dp[j]=dp1[j]; dp1[j]=0.0; } } printf("%.3lf ",dp[m]); }
二维的写法;好理解
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; double dp[11000][110]; //dp[i][j]代表的是取球i次,最终桌面上有j个球的概率 ll c,n,m; int main(){ cin>>c>>n>>m; dp[0][0]=1.0; if(n>=10000) n=10000+(n%2); for(int i=1;i<=n;i++){ for(int j=0;j<=c;j++){ if(j) dp[i][j]+=dp[i-1][j-1]*((c-j+1)/(c*1.0)); if(j!=c) dp[i][j]+=dp[i-1][j+1]*((j+1)*1.0/(c*1.0)); } } //可以测试一下,向后都是收敛的了 // for(int i=1e4-10;i<=1e4;i++){ // printf("%.3lf ",dp[i][m]); // } printf("%.3lf",dp[n][m]); }