题意:给你n个杯子,每个杯子有一定水;
接下来n个操作,表示第i个杯子的水均分到指定的杯子;
求经过m次操作后,各个杯子的水量;
思路:矩阵快速幂;
#include<cstdio>
#include<stdlib.h>
#include<string.h>
#include<string>
//#include<map>
#include<cmath>
#include<iostream>
#include <queue>
#include <stack>
#include<algorithm>
#include<set>
using namespace std;
#define INF 1e8
#define inf -0x3f3f3f3f
#define eps 1e-8
#define LL long long
#define maxn 10
#define mol 100000007
int num;
struct matrix
{
double a[30][30];//把每次倒水的比率提取出来放在这里面,例如i倒给j几分之几,以便进行计算
}origin,answ;//answ保存提取出来比率计算后的答案
matrix multiply(matrix x,matrix y)//x与y的矩阵乘法
{
matrix temp;
for(int i=1;i<=num;i++)
{
for(int j=1;j<=num;j++)
{
double ans=0;
for(int k=1;k<=num;k++)
{
ans+=x.a[i][k]*y.a[k][j];
}
temp.a[i][j]=ans;
}
}
return temp;
}
matrix calc(int n)//矩阵快速幂——把提取出来的比率进行n次重复的‘倒’,即n次幂
{
while(n)//以下运用二分
{
if(n%2==1)
answ=multiply(origin,answ);
origin=multiply(origin,origin);
n/=2;
}
return answ;
}
int main()
{
int t,n,k,m;
double a[30];
scanf("%d",&t);
for(int id=0;id<t;id++)
{
memset(answ.a,0,sizeof(answ.a));
memset(origin.a,0,sizeof(origin.a));
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
num=n;
for(int i=1;i<=n;i++)
answ.a[i][i]=1;
for(int i=1;i<=n;i++)
{
scanf("%d",&k);//i要平均的倒给之后的k个人
if(k==0)
origin.a[i][i]=1.0;//不向任何地方倒,相当于都倒给自己,即1/1
for(int j=1;j<=k;j++)
{
int p;
scanf("%d",&p);
origin.a[p][i]=1.0/k;//i倒给p的比率
}
}
scanf("%d",&m);
calc(m);//对数据进行处理
for(int i=1;i<=n;i++)//逐个输出答案
{
double ans=0;//初始化
for(int j=1;j<=n;j++)//一列一列处理
ans+=answ.a[i][j]*a[j];//处理后的比率*原始数据
if(i==1)
printf("%.2lf",ans);
else
printf(" %.2lf",ans);
}
puts("");
}
return 0;
}