题意:每一分钟,每个杯子都要向其他K个杯子倒水,这K个杯子每个道K分之一的水。每次倒水都是所有杯子同时进行。问经过M分钟每个杯子有多少水。
思路:快速幂。
第一遍写的时候竟然脑残的认为最后杯子里的水会趋近一个常数。。。
代码如下:
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<map>
#include<cmath>
#include<assert.h>
#include<iomanip>
#include<assert.h>
using namespace std;
const int maxn = 25;
struct Matrix
{
int n,m;
double a[maxn][maxn];
Matrix(int _n=0,int _m=0):n(_n),m(_m){memset(a,0,sizeof(a));}
void clear(){
memset(a,0,sizeof(a));
}
void E()
{
memset(a,0,sizeof(a));
for(int i=0;i<n;++i){
a[i][i]=1;
}
}
Matrix operator * (const Matrix &b) const {
Matrix tmp;
tmp.clear();
tmp.n = n;tmp.m = b.m;
for(int i=0;i<n;++i){
for(int j=0;j<b.m;++j){
for(int k=0;k<m;++k)tmp.a[i][j] += a[i][k] * b.a[k][j];
}
}
return tmp;
}
};
Matrix fpow(Matrix a,int m)
{
Matrix ret=Matrix(a.n,a.m);
ret.E();
while(m){
if(m&1){
ret = ret *a;
}
a=a*a;
m>>=1;
}
return ret;
}
int main()
{
// freopen("data.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
Matrix c = Matrix(n,1);
for(int i=0;i<n;++i){
scanf("%lf",&c.a[i][0]);
}
Matrix M=Matrix(n,n);
for(int i=0;i<n;++i){
int k;
scanf("%d",&k);
if(k==0){
M.a[i][i] = 1;
}
double tmp = 1/(double)k;
for(int j=0;j<k;++j){
int d;
scanf("%d",&d);
d--;
M.a[d][i] = tmp;
}
}
int ti;
scanf("%d",&ti);
M=fpow(M,ti);
c = M*c;
printf("%.2lf",c.a[0][0]);
for(int i=1;i<n;++i){
printf(" %.2lf",c.a[i][0]);
}
puts("");
}
return 0;
}