解题报告——概率期望

因为概率与期望没什么知识点,所以直接上题吧:

1、

Rimi learned a new thing about integers, which is - any positive integer greater than 1 can be divided by its divisors. So, he is now playing with this property. He selects a number N. And he calls this D.

In each turn he randomly chooses a divisor of D (1 to D). Then he divides D by the number to obtain new D. He repeats this procedure until D becomes 1. What is the expected number of moves required for N to become 1.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case begins with an integer N (1 ≤ N ≤ 105).

Output

For each case of input you have to print the case number and the expected value. Errors less than 10-6 will be ignored.

Sample Input

3

扫描二维码关注公众号,回复: 2345550 查看本文章

1

2

50

Sample Output

Case 1: 0

Case 2: 2.00

Case 3: 3.0333333333

这是概率与期望中最为基础的题,就算没有接触过概率与期望,应该也能做出来。

dp i 表示i到1的期望步数 = i 所有的因子dp值平均数+1

但是我们发现i本身也为i的因子,但是dpi的值还没有求出,所以我们只要把这一项移到左边去就行了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int n, a[100002], Max;
double dp[100002];
vector<int> g[100002];
int main()
{
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		scanf("%d", &a[i]);
		Max = max(Max, a[i]);
	}
	for(int i = 2; i <= Max; i++){
		for(int j = 1; j <= sqrt(i); j++){
			if(i % j == 0){
			if(j * j != i){
				g[i].push_back(j);
				g[i].push_back(i/j);
			}
			else g[i].push_back(j);
			}
		}
	}
	dp[1] = 0;
	for(int i = 2; i <= Max; i++){
	    int sum = g[i].size();
		for(int j = 0; j < sum; j++)
		{
			if(g[i][j] != i)
				dp[i] += dp[g[i][j]];
		}
		dp[i]/=sum;
		dp[i]++;
		dp[i] = dp[i] / (sum - 1) * sum;
	}
	for(int i = 1; i <= n; i++)
	   printf("Case %d: %lf\n", i, dp[a[i]]);
	return 0;
}
			    

2、

There is a very simple and interesting one-person game. You have 3 dice, namely Die1, Die2 and Die3. Die1 has K1 faces. Die2 has K2 faces. Die3 has K3 faces. All the dice are fair dice, so the probability of rolling each value, 1 to K1, K2, K3 is exactly 1 / K1, 1 / K2 and 1 / K3. You have a counter, and the game is played as follow:

Set the counter to 0 at first.
Roll the 3 dice simultaneously. If the up-facing number of Die1 is a, the up-facing number of Die2 is b and the up-facing number of Die3 is c, set the counter to 0. Otherwise, add the counter by the total value of the 3 up-facing numbers.
If the counter's number is still not greater than n, go to step 2. Otherwise the game is ended.
Calculate the expectation of the number of times that you cast dice before the end of the game.

Input
There are multiple test cases. The first line of input is an integer T (0 < T <= 300) indicating the number of test cases. Then T test cases follow. Each test case is a line contains 7 non-negative integers n, K1, K2, K3, a, b, c (0 <= n <= 500, 1 < K1, K2, K3 <= 6, 1 <= a <= K1, 1 <= b <= K2, 1 <= c <= K3).


Output
For each test case, output the answer in a single line. A relative error of 1e-8 will be accepted.


Sample Input
2
0 2 2 2 1 1 1
0 6 6 6 1 1 1

Sample Output
1.142857142857143
1.004651162790698

这是一道比较难的题,很容易地,我们会想出递推,先处理出3个色子能够投出的所有值以及其的概率,再用dp去转移。但是我们发现对于a,b,c清0的特殊情况,我们没法去求,因为我们是倒着递推的。

这里提供了一种思路,我们发现对于每一个dp【i】值都含有dp【0】这个未知的值。并且概率之间存在一次函数关系。所以我们对于每一个dp值都设为dp【i】 = A【i】× dp【0】 + B【i】 的形式

图片来自大佬博客

所以我们求出A的值与B的值,dp[0] = A[0] * dp[0] + B[0] 所以移项求dp0即可

#include<bits/stdc++.h>
using namespace std; 
double A[502], B[502], p[40];
int n, k1, k2, k3, a, b, c, t;
int main()
{
    scanf("%d", &t);
	while(t--){
		memset(A, 0, sizeof(A));
		memset(B, 0, sizeof(B));
		memset(p, 0, sizeof(p));
    scanf("%d %d %d %d %d %d %d", &n, &k1, &k2, &k3, &a, &b, &c);
	for(int i = 1; i <= k1; i++)
		for(int j = 1; j <= k2; j++)
			for(int k = 1; k <= k3; k++)
				if(!(i == a && j == b && c == k))
                   	p[i + j + k] += 1.0/k1/k2/k3;
    for(int i = n; i >= 0; i--)
    {
		for(int j = 1; j <= k1 + k2 + k3; j++)
        {
            A[i] += A[i + j] * p[j];
            B[i] += B[i + j] * p[j];	
		}
        A[i] += 1.0/k1/k2/k3;
        B[i] += 1.0;
	}
    printf("%.16lf\n", B[0]/(1.0 - A[0]));
    }	
}

3、

Hzz loves aeroplane chess very much. The chess map contains N+1 grids labeled from 0 to N. Hzz starts at grid 0. For each step he throws a dice(a dice have six faces with equal probability to face up and the numbers on the faces are 1,2,3,4,5,6). When Hzz is at grid i and the dice number is x, he will moves to grid i+x. Hzz finishes the game when i+x is equal to or greater than N. 

There are also M flight lines on the chess map. The i-th flight line can help Hzz fly from grid Xi to Yi (0<Xi<Yi<=N) without throwing the dice. If there is another flight line from Yi, Hzz can take the flight line continuously. It is granted that there is no two or more flight lines start from the same grid. 

Please help Hzz calculate the expected dice throwing times to finish the game. 

Input

There are multiple test cases. 
Each test case contains several lines. 
The first line contains two integers N(1≤N≤100000) and M(0≤M≤1000). 
Then M lines follow, each line contains two integers Xi,Yi(1≤Xi<Yi≤N).   
The input end with N=0, M=0. 

Output

For each test case in the input, you should output a line indicating the expected dice throwing times. Output should be rounded to 4 digits after decimal point. 

Sample Input

2 0
8 3
2 4
4 5
7 8
0 0

Sample Output

1.1667
2.3441

这题非常简单,从后往前递推,跳跃的直接相等就行了

#include<bits/stdc++.h>
using namespace std;
int t[100002], n, m;
double dp[100002];
int main()
{
	while(scanf("%d %d", &n, &m)){
	if(n == 0 && m == 0) break;
	memset(dp, 0, sizeof(dp));
	memset(t, 0, sizeof(t)); 
	for(int i = 1; i <= m; i++){
		int x,y;
		scanf("%d %d", &x, &y);
		t[x] = y;
	}
	for(int i = n - 1; i >= 0; i--){
		if(t[i]) 
		{
			dp[i] = dp[t[i]];
			continue;
		}
		for(int j = 1; j <= 6; j++){
			dp[i] += dp[i + j];
		}
		dp[i]/=6.0;
		dp[i]+=1.0;
	}
	printf("%.4lf\n", dp[0]);
    }
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/gjc2561571372/article/details/81157198