51nod1836-戰忽局的手段【期望dp,矩陣乘法】
阿新 • • 發佈:2021-08-01
正題
題目連線:http://www.51nod.com/Challenge/Problem.html#problemId=1836
題目大意
\(n\)個點\(m\)次隨機選擇一個點標記(可以重複),求最後被標記點的期望個數。
\(1\leq n,m\leq 10^{18}\)
解題思路
額開始拿方案數推了半天后面發現要斯特林數就放棄了,然後換了種方法發現很簡單?
設\(i\)輪之後被標記點的期望個數是\(f_i\),那麼有
\[f_i=f_{i-1}+\frac{n-f_{i-1}}{n} \]\[f_i=f_{i-1}\frac{n-1}{n}+1 \]然後矩陣乘法就好了。
有一說一我第一次用期望值來算概率(((
時間複雜度\(O(T\log n)\)
code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int S=2; struct Matrix{ __float128 a[S][S]; }f,ans,c; long long T,n,m; Matrix operator*(const Matrix &a,const Matrix &b){ c.a[0][0]=c.a[0][1]=c.a[1][0]=c.a[1][1]=0; for(int i=0;i<S;i++) for(int j=0;j<S;j++) for(int k=0;k<S;k++) c.a[i][j]+=a.a[i][k]*b.a[k][j]; return c; } int main() { scanf("%lld",&T); while(T--){ scanf("%lld%lld",&n,&m); f.a[1][1]=(__float128)(n-1)/n; f.a[0][1]=f.a[0][0]=1;f.a[1][0]=0; ans.a[0][0]=1;ans.a[0][1]=0; while(m){ if(m&1)ans=ans*f; f=f*f;m>>=1; } printf("%.12lf\n",(double)ans.a[0][1]); } return 0; }