山东省第五届ACM省赛 Circle(高斯消元)

13 篇文章 0 订阅
13 篇文章 0 订阅

Problem Description

You have been given a circle from 0 to n - 1. If you are currently at x, you will move to (x - 1) mod n or (x + 1) mod n with equal probability. Now we want to know the expected number of steps you need to reach x from 0.

Input

The first line contains one integer T — the number of test cases.

Each of the next T lines contains two integers n, x (0  ≤ x < n ≤ 1000) as we mention above.

Output

For each test case. Print a single float number — the expected number of steps you need to reach x from 0. The figure is accurate to 4 decimal places.

Example Input

3
3 2
5 4
10 5

Example Output

2.0000
4.0000
25.0000

题目大意

有一个从0~n-1的环,从一个点可以向左右两个点移动一步且概率相等,问从 0 移动到 x 的期望是多少

解题思路

E[p]表示从0节点到p节点走的步数的期望值,则E[x]=0;对于任意一个节点来说,可从左侧走过来,也可以是从右侧走过来,即有 E[p]=0.5(E[p-1]+1)+0.5(E[p+1]+1),化简则有 -0.5*E[p-1]+E[p]-0.5*E[p+1]=1。
则可得 n 个方程组,有 n 个未知量。高斯消元求解即可。

代码实现

#include <iostream>
#include <cstring>
#include <cmath>
#include<cstdio>
using namespace std;
#define maxn 1007
double a[maxn][maxn];
int equ,var;
double x[maxn];
bool free_x[maxn];
int n;
void gauss()
{
    equ=n,var=n;
    int i,j,k;
    int max_r;
    int col;
    double temp;
    col=0;
    for(k=0;k<equ&&col<var;k++,col++)
    {
        max_r=k;
        for(i=k+1;i<equ;i++)
        {
            if(fabs(a[i][col])-fabs(a[max_r][col])>0)
                max_r=i;
        }
        if(max_r!=k)
        {
            for(j=k;j<var+1;j++)
                swap(a[k][j],a[max_r][j]);
        }
        if(a[k][col]==0)
        {
            k--;
            continue;
        }
        for(i=k+1;i<equ;i++)
        {
            if (a[i][col]!=0)
            {
                temp=a[i][col]/a[k][col];
                for(j=col;j<var+1;j++)
                {
                    a[i][j]=a[i][j]-a[k][j]*temp;
                }
            }
        }
    }
    for (i=var-1;i>=0;i--)
    {
        temp=a[i][var];
        for(j=i+1;j<var;j++)
        {
            if(a[i][j]!=0)
                temp-=a[i][j]*x[j];
        }
        x[i]=temp/a[i][i];
    }
    return;
}
int main()
{
    int T,xx;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&xx);
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
        {
            if(i==xx)
            {
                a[i][i]=1;
                a[i][n]=0;
                continue;
            }
            a[i][i]=1;
            a[i][n]=1;
            a[i][(i-1+n)%n]=-0.5;
            a[i][(i+1)%n]=-0.5;
        }
        gauss();
        printf("%.4lf\n",x[0]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值