这题虽然我不会,但是弄懂了滚动数组的一些坑
1.滚动的那一维度一定放在最外层。原因:若放在里层,则不一定遍历到其他维度所有的值。
2.滚动的时候注意每次滚动时都要赋初值。因为对于滚动的那一维度的数值不同,对应的初值也可能不同。
3.对于不成立的状态,要注意一定要赋值,否则与上一次循环的一样就凉了
4.所有数组滚动的维度必须一样,否则无法统一最外层的循环变量。至于如果最后统计答案的时候需要其他维度的值,则在dp的过程中记录在其他数组中。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef int lint;
const lint maxm = 300;
LL A[2][maxm][maxm],dp[2][maxm][maxm],sumA[2][maxm][maxm],sumdp[2][maxm][maxm],B[2][maxm];
int main(){
lint M,N;
while( cin >> M >> N ){
memset( dp,0,sizeof( dp ) );
memset( sumA,0,sizeof( sumA ) );
memset( A,0,sizeof( A ) );
memset( sumdp,0,sizeof( sumdp ) );
for( lint i = 0;i <= M;i++ ){
for( lint j = 0;j <= M;j++ ) {
sumA[0][i][j] = 1;
dp[0][i][j] = A[0][i][j] = sumdp[0][i][j] = 0;
}
}
for( lint i = 0;i <= M;i++ ){
A[0][i][0] = 1;sumdp[0][0][i] = 1;
}
dp[0][0][0] = 1;
for( lint t = 1;t <= M;t++ ){
for( lint i = 0;i <= M;i++ ) {
dp[t % 2][0][i] = A[t % 2][0][i] = sumdp[t % 2][0][i] = sumA[t % 2][0][i] = 0;
dp[t % 2][i][0] = A[t % 2][i][0] = sumdp[t % 2][i][0] = sumA[t % 2][i][0] = 0;
}
for( lint x = 1;x <= M;x++ ){
for( lint m = 1;m <= M;m++ ){
A[t%2][x][m] = sumA[(t-1)%2][x][m-1] - ((m-x-1 < 0)? 0 : sumA[(t-1)%2][x][m-x-1]);
sumA[t%2][x][m] = sumA[t%2][x][m-1] + A[t%2][x][m];
lint dt = 0;
if( m-x >= -1 )
dt += sumdp[(t-1)%2][x][m-1] - ((m-x == -1) ? 0: sumdp[(t-1)%2][x][m-x]);
if( m - x >= 0 )
dt += A[(t-1)%2][x][m-x];
dp[t%2][x][m] = dt;
sumdp[t%2][x][m] = sumdp[t%2][x][m-1] + dp[t%2][x][m];
if( m == M ) B[t][x] = dp[t%2][x][m];
// cout << dp[t%2][x][m] << " " ;
}
}
// cout << endl;
}
//cout << 1 << endl;
ld C = 1;
long double ans = 0;
for (int k = 1;k <= M;k++)C *= ((long double)k) / ((long double)N - 1 + k);
for (int t = 1;t <= M&&t <= N;t++)
{
C *= (long double)(N - t + 1) / (long double)t;
for (int x = 1;x <= M;x++)
{
//if (B[x][t])printf("%lld\n", B[x][t]);
ans += x*B[t][x] * C;
//cout << ans << endl;
}
}
fflush(stdout);
printf("%.4f\n", (double)ans);
}
return 0;
}