[BZOJ2510] 弱题 [矩阵乘+循环矩阵优化]
式子是最基本的,通过式子:
$f[i][j]=(1/m)*f[i-1][j-1]+(1-1/m)*f[i-1][j] (1<j<=n)$
$f[i][1]=(1/m)*f[i-1][n]+(1-1/m)*f[i-1][1] $
对于这个式子我是这么理解的,首先把它拆开:
$f[i][j]=f[i-1][j]+(1/m)*f[i-1][j-1]-(1/m)*f[i-1][j] $
也就是说上一轮期望值+选中j-1的概率×期望1-选中j的概率×期望1
矩阵快速幂?$ O(n^3log2(k))$ 瞬间爆炸
可以从上表中发现规律:这是一个循环矩阵!
所以我们可以通过循环矩阵的式子:
f[x]=sigma a[i]*b[j] ((i+j-2)%n+1==x)
于是就 $ O(n^2log2(k))$ 解决了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define r register
using namespace std;
int n,m,k;
struct Ma{double f[1050];}A,B;
Ma X(Ma x,Ma y)
{
Ma ans;
memset(ans.f,0,sizeof(ans.f));
for(r int j=1;j<=n;j++)
{
for(r int k=1;k<=n;k++)
{
ans.f[(j+k-2)%n+1]+=x.f[j]*y.f[k];
}
}
return ans;
}
Ma poww(Ma x,int y)
{
Ma ans;
memset(ans.f,0,sizeof(ans.f));
ans.f[1]=1;
while(y)
{
if(y&1) ans=X(x,ans);
y>>=1;
x=X(x,x);
}
return ans;
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
if(m==0)
{
for(int i=1;i<=n;i++) puts("0.000");
return 0;