題目大意
一開始有
數據範圍
題解
設
那麼我們再做些更正,即
而且可以發現的一點是,當
還有一點是,當
接來下考慮怎麼求答案。
設
j=1
那麼只需要第二個格子不是1就好了。可以得到遞推式
dpi,j=j+∑50k=2dpi−1,k∗Bi−1,k∑50k=2Bi−1,k
這就是爲什麼我們要預處理出
而且遞推式的分母其實就是出現這種情況的概率。
2.
可以發現的是,第二個格子的值必然比
但這題到這裏還沒結束,因爲
但之前說了,由於
那麼我們最終的答案就是
代碼:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 55;
typedef double Matrix[MAXN][MAXN];
Matrix A,B,Trans,Dp,Cur;
double Out[55];
int N;
void Mul(Matrix &a,Matrix &b,Matrix &c)
{
static Matrix Tmp;
memset(Tmp,0,sizeof Tmp);
for(int i = 0;i <= 50;i ++)
for(int k = 0;k <= 50;k ++)
for(int j = 0;j <= 50;j ++)
Tmp[i][j] += a[i][k] * b[k][j];
memcpy(c,Tmp,sizeof c);
}
int main()
{
// freopen("data.in","r",stdin),freopen("data.out","w",stdout);
double p,q;
scanf("%d%lf", &N, &p);
p = p / (1e9),q = 1 - p;
for(int i = 1;i <= 50;i ++)
for(int j = 1;j <= 50;j ++)
{
if (j == 1) A[i][j] += p;
if (j == 2) A[i][j] += q,B[i][j] += q;
A[i][j] += A[i][j - 1] * A[i - 1][j - 1];
B[i][j] += B[i][j - 1] * A[i - 1][j - 1];
}
for(int i = 50;i;i --)
for(int j = 1;j <= 50;j ++)
A[i][j] *= (1 - A[i - 1][j]),B[i][j] *= (1 - A[i - 1][j]);
for(int j = 1;j <= 50;j ++) Dp[1][j] = j;
for(int i = 2;i <= 50;i ++)
for(int j = 1;j <= 50;j ++)
{
double s = 0;
if (j == 1)
{
for(int k = 2;k <= 50;k ++) Dp[i][j] += Dp[i - 1][k] * B[i - 1][k],s += B[i - 1][k];
} else
for(int k = 1;k < j;k ++) Dp[i][j] += Dp[i - 1][k] * A[i - 1][k],s += A[i - 1][k];
Dp[i][j] /= s;
Dp[i][j] += j;
}
Trans[0][0] = 1;
for(int j = 1;j <= 50;j ++) Trans[0][j] = j;
//For j = 1
double s = 0;
for(int k = 2;k <= 50;k ++) s += B[50][k];
for(int k = 2;k <= 50;k ++) Trans[k][1] += B[50][k] / s;
//For j not equal 1
for(int j = 2;j <= 50;j ++)
{
s = 0;
for(int k = 1;k < j;k ++) s += A[50][k];
for(int k = 1;k < j;k ++) Trans[k][j] += A[50][k] / s;
}
int bk = N;
if (N > 50)
{
memcpy(Cur[0],Dp[50],sizeof Cur);
Cur[0][0] = 1;
for(N -= 50;N;N >>= 1)
{
if (N & 1) Mul(Cur,Trans,Cur);
Mul(Trans,Trans,Trans);
}
memcpy(Out,Cur[0],sizeof Out);
} else memcpy(Out,Dp[N],sizeof Out);
double ans = 0;
for(int j = 1;j <= 50;j ++) ans += Out[j] * A[bk > 50 ? 50 : bk][j];
printf("%.15f\n", ans);
return 0;
}