本文主要是介绍51nod 1836 战忽局的手段(期望+矩阵快速幂),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
众所周知,有一个神秘的组织——战忽局,在暗中保护着我们。在局中任职的官员都有着极强的忽悠技巧,不只能用预言,还能用往事忽悠人。如今某外星间谍已经获得了战忽局曾经参与的n次事件的资料,局座发现了这件事,于是决定再次用忽悠来保证战忽局的安全。局座将发表m次演讲,每一天他都会从n事件中等概率地挑选一件混淆众人,由于局座每天很忙,不能把之前将的事件都记录下来,因此他可能会重复选择某一件事。现在局座想知道,m次演讲过后,期望能使多少事件混淆众人。
Input
第一行一个整数T(1<=T<=1000),表示数据组数。接下来T行每行两个正整数n,m(1<=n,m<=1e18)分别表示事件数和局座演讲的次数。
Output
对于每组数据输出一行一个实数ans,表示局座在m次演讲之后期望混淆众人的事件数,你输入的数和标准答案的相对误差不超过1e-6视为正确。
Input示例
3
2 2
10 100000
3 2
Output示例
1.5000000
10.0000000
1.6666667
解题思路
设f(i)为第i次演讲后期望混淆众人的事件数,则 f(i+1)=f(i)n∗f(i)+n−f(i)n∗(f(i)+1) ,化简之后可得: f(i+1)=n−1n∗f(i)+1 ,构造矩阵,利用矩阵快速幂求解。
代码实现
#include<bits/stdc++.h>
using namespace std;
#define ff __float128
#define ll long long
#define maxn 2
struct matrix
{ff f[maxn][maxn];
}ans,ori;
matrix multi(matrix a,matrix b)
{matrix c;for(int i=0;i<maxn;i++)for(int j=0;j<maxn;j++){c.f[i][j]=0;for(int k=0;k<maxn;k++){c.f[i][j]+=a.f[i][k]*b.f[k][j];}}return c;
}void quick_pow(ll num)
{memset(ans.f,0,sizeof(ans.f));ans.f[0][0]=ans.f[1][1]=1;while(num>0){if(num%2){ans=multi(ans,ori);}ori=multi(ori,ori);num/=2;}
}int main()
{int T;ll n,m;scanf("%d",&T);while(T--){scanf("%I64d %I64d",&n,&m);ori.f[0][0]=(ff)(n-1)/n,ori.f[0][1]=0;ori.f[1][0]=1,ori.f[1][1]=1;quick_pow(m);double cnt=ans.f[1][0];printf("%.7f\n",cnt);}return 0;
}
这篇关于51nod 1836 战忽局的手段(期望+矩阵快速幂)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!