开始的时候被数据吓到了,最后看了别人博客发现是可以缩减的。
状态方程:
//dp[i][j]表示取i次还剩j个的概率
//dp[i][j] = dp[i-1][j-1] * ( C - j + 1 ) / C + dp[i-1][j+1] * ( j + 1 ) / C;
因为这是收敛的,所以当i一定大的时候,由于精度的问题,可以不再计算,然后通过找规律可以发现:
图片来自:hi.baidu.com/ycdoit/item/e744f216decf1959f0090e60
可以发现到最后只是奇偶交换而已
这一题的讨论中说N大于1000的时候分奇偶,其实我试了一下,发现当N为300的时候就可以分了。。。。
so。。。。
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
double dp[1100][110];
double C;
int N, M;
int main(){
while( cin >> C && C ){
cin >> N >> M;
if( N > 300 ){
N = N % 2 + 1000;
}
memset( dp, 0, sizeof( dp ) );
dp[0][0] = 1;
for( int i = 1; i <= N; i++ ){
for( int j = 0; j <= i && j <= C; j++ ){
if( j == 0 ){
dp[i][j] = dp[i-1][j+1] * ( j + 1 ) / C;
}else if( j == C || j == i ){
dp[i][j] = dp[i-1][j-1] * ( C - j + 1 ) / C;
}else{
dp[i][j] = dp[i-1][j-1] * ( C - j + 1 ) / C + dp[i-1][j+1] * ( j + 1 ) / C;
}
}
}
if( M > C ){
cout << 0 << endl;
}else
cout << dp[N][M] << endl;
}
return 0;
}