您的位置:首页 > 其它

51nod 1836(矩阵快速幂,求期望,__float128)

2018-01-28 20:10 316 查看
/*

    51nod 1836

    众所周知,有一个神秘的组织——战忽局,在暗中保护着我们。

    在局中任职的官员都有着极强的忽悠技巧,不只能用预言,还能用往事忽悠人。

    如今某外星间谍已经获得了战忽局曾经参与的n次事件的资料,

    局座发现了这件事,于是决定再次用忽悠来保证战忽局的安全。

    局座将发表m次演讲,每一天他都会从n事件中等概率地挑选一件混淆众人,

    由于局座每天很忙,不能把之前将的事件都记录下来,因此他可能会重复选择某一件事。

    现在局座想知道,m次演讲过后,期望能使多少事件混淆众人。

    设f[i]为忽悠i次之后期望的事件数

    那么有f[i-1]/n的概率是以前忽悠过的事件,其事件数就为f[i-1]

    以及1-f[i-1]/n的概率是以前未忽悠过的事件,其事件数就为(f[i-1]+1)

    所以

    f[i]=f[i-1]/n*f[i-1]+(1-f[i-1]/n)*(f[i-1]+1)

    化简后得

    f[i]=f[i-1]*((n-1)/n)*f[i-1]+1

    然后构造矩阵

    A={(n-1)/n  1 }

      {    0    1 }

    另外此题卡了一下精度

    用黑科技__float128来保存精度

    最后转变成double输出即可

*/

#include <iostream>

#include <algorithm>

#include <stdio.h>

#include <math.h>

#include <string.h>

#define MAX 3

#define ll long long

using namespace std;

struct matrix

{

    __float128 m[MAX][MAX];

};

matrix matrixmul(matrix a,matrix b)

{

    matrix c;

    for(int i=1; i<MAX; i++)

        for(int j=1; j<MAX; j++)

        {

            c.m[i][j]=0;

            for(int k=1; k<MAX; k++)

                c.m[i][j]+=(a.m[i][k]*b.m[k][j]);

        }

    return c;

}

matrix quickpow(matrix m,ll n)

{

    matrix b;

    memset(b.m,0,sizeof(b.m));

    for(int i = 1; i < MAX; i++)

        b.m[i][i] = 1;

    while(n>=1)

    {

        if(n&1)

            b=matrixmul(b,m);

        n=n>>1;

        m=matrixmul(m,m);

    }

    return b;

}

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        ll n,i;

        cin>>n>>i;

        matrix a;

        a.m[1][1]=(__float128)(n-1)/n;a.m[1][2]=1;

        a.m[2][1]=0;a.m[2][2]=1;

        matrix res=quickpow(a,i-1);

        double ans=(double)res.m[1][1]+res.m[1][2];

        printf("%.12lf\n",ans);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: