#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
void Run(int x = 0) {
#ifdef ACM //宏定义免注释 freopen
if(! x) fre(); else Fre();
#endif
}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define db double
#define ll long long
#define ull unsigned long long
#define Pir pair
#define m_p make_pair
#define for_(i, s, e) for(ll i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(ll i = (ll)(e); i >= (ll)(s); i --)
#define memset(a, b, c) memset(a, (int)b, c);
#define size() size() * 1LL
#define sc scanf
#define pr printf
#define sd(a) sc("%lld", &a)
#define ss(a) sc("%s", a)
#define __ pr( "------------------------\n" );
#define ___ pr("\n------------------------\n");
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
/*=========================ACMer===========================*/
const ll mxn = 1e3;
db a[mxn], dp[mxn];
int main()
{
Run();
ll T, cas = 1; sd(T);
while(T --)
{
ll n; sd(n);
for_(i, 1, n) sc("%lf", &a[i]);
memset(dp, 0, sizeof dp);
dp[1] = 1;
for_(i, 1, n)
{
ll mx = min(n, i + 6);
for_(j, i + 1, mx)
{
dp[j] += dp[i] / (mx - i);
}
}
db sum = 0;
for_(i, 1, n) sum += dp[i] * a[i];
pr("Case %lld: %.6f\n", cas ++, sum);
}
return 0;
}
链接:https://www.cnblogs.com/6262369sss/p/8987216.html
为什么只有从后往前才会符合推理 因为从前往后的概率分布是不均匀的。 从 a [i-6] 到 a [i] 的概率并不是 1/6,因为 a
[i-6] 可以先到 a [i-5],再到 a [i],所以实际上,a [i-6] 到 a [i] 的 概率是低于其他值的,因为其他值到 a [i] 的概率是要先算上 a [i-6] 没有成功抵达
a [i] 的概率。不能以 1 开始,因为状态方程只能为 a [i]=1/6a[i+1]+ 1/6a[i+2]+……+1/6a [i+6] 假如我们令方程为
a[i]=1/6 a[i-1]+ 1/6a[i-2]+……+1/6a[i-6] a[2]=a[1]+a[2]
a [3]=0.5a [1]+0.5a [2]+a [3]=a [1]+0.5a [2]+a [3] 那么
a [4]=1/3a [1]+1/3a [2]+1/3a [3]+a [4]=a [1]+0.5a [2]+1/3a [3]+a [4] 然而实际上 a
[4] 的期望并不是这样 如果 1 到 4。 从 1 开始,到 2 的概率为 1/3,到 3 的概率为 1/3 加上 2 到 3 的概率,为
0.5。 所以正确的是 a [4]=a [1]+1/3a [2]+0.5a [3]+a [4]。其实逆推可以保证一直是从里面推到外面而且概率是正确的。
因为先算 3->4 的得出 dp [3]=a [3]+a [4]
再算 2->4 的,得到 2->3 (然后再到 4), 以及 2->4,dp [2] = dp [3]/2 (2->3->4) + dp
[4]/2 (2->4) + a [2],这里面又用到 3->4 的期望 dp [3]然后类比这个处理过程,每次都从内到外的计算,就不会出现概率不对的情况了。
就像进行数运算时先考虑最里面的括号,算出来答案,然后再考虑次里面的括号,由内到外的算出答案。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
void Run(int x = 0) {
#ifdef ACM //宏定义免注释 freopen
if(! x) fre(); else Fre();
#endif
}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define db double
#define ll long long
#define ull unsigned long long
#define Pir pair
#define m_p make_pair
#define for_(i, s, e) for(ll i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(ll i = (ll)(e); i >= (ll)(s); i --)
#define memset(a, b, c) memset(a, (int)b, c);
#define size() size() * 1LL
#define sc scanf
#define pr printf
#define sd(a) sc("%lld", &a)
#define ss(a) sc("%s", a)
#define __ pr( "------------------------\n" );
#define ___ pr("\n------------------------\n");
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
/*=========================ACMer===========================*/
const ll mxn = 1e3;
db a[mxn], dp[mxn];
int main()
{
Run();
ll T, cas = 1; sd(T);
while(T --)
{
ll n; sd(n);
for_(i, 1, n) sc("%lf", &dp[i]);
rep_(i, n, 1)
{
ll mx = min(n, i + 6);
for_(j, i + 1, mx)
{
dp[i] += dp[j] / (mx - i);
}
}
pr("Case %lld: %.6f\n", cas ++, dp[1]);
}
return 0;
}