您的位置:首页 > 大数据 > 人工智能

POJ 3735 Training little cats(矩阵快速幂)

2015-09-02 13:02 423 查看
Description

有n只猫,开始时每只猫都没有花生,三种操作

g x:给第x只猫一个花生

e x:第x只猫把它所拥有的花生都吃完

s x y:第x只猫与第y只猫交换所拥有的所有花生

现在给出k中操作以及循环数m,问在进行了m次这k次操作后每只猫分别有多少个花生

Input

多组输入u,每组用例第一行为三个整数n,m,k分别表示猫数,操作循环数以及操作数,之后k行每行一个操作,以0 0 0结束输入

Output

对于每组用例,输出m轮k次操作后每只猫所拥有的花生数

Sample Input

3 1 6

g 1

g 2

g 2

s 1 2

g 3

e 2

0 0 0

Sample Output

2 0 1

Solution

将每只猫的花生数放在一个1*n的矩阵中,考虑用k次操作构造成一个n*n矩阵A,因为三种操作中存在某种猫的花生数加一的操作,所以要把矩阵扩展一位放1,即[1,cnt1,cnt2,…,cntn],初始化矩阵A为单位矩阵,对于操作1,要把A[0][x]++;对于操作2,要令A[i][x]=0;对于操作3,要swap(A[i][x],A[i][y]),构造出A矩阵之后用矩阵快速幂求出A^m后第一行元素即为操作后每只猫的花生数

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 111
typedef long long ll;
struct Mat
{
ll mat[maxn][maxn];//矩阵
ll row,col;//矩阵行列数
};
Mat mod_mul(Mat a,Mat b)//矩阵乘法
{
Mat ans;
ans.row=a.row;
ans.col=b.col;
memset(ans.mat,0,sizeof(ans.mat));
for(ll i=0;i<ans.row;i++)
for(ll k=0;k<a.col;k++)
if(a.mat[i][k])
for(ll j=0;j<ans.col;j++)
ans.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
return ans;
}
Mat mod_pow(Mat a,ll k)//矩阵快速幂
{
Mat ans;
ans.row=a.row;
ans.col=a.col;
for(ll i=0;i<a.row;i++)
for(ll j=0;j<a.col;j++)
ans.mat[i][j]=(i==j);
while(k)
{
if(k&1)ans=mod_mul(ans,a);
a=mod_mul(a,a);
k>>=1;
}
return ans;
}
int main()
{
ll n,m,k;
while(scanf("%lld%lld%lld",&n,&m,&k),n||m||k)
{
Mat ans;//初始化一个(n+1)*(n+1)的单位矩阵
ans.row=ans.col=n+1;
for(ll i=0;i<ans.row;i++)
for(ll j=0;j<ans.col;j++)
ans.mat[i][j]=(i==j);
while(k--)
{
char op[3];
ll x,y;
scanf("%s",op);
if(op[0]=='g')
{
scanf("%lld",&x);
ans.mat[0][x]++;
}
else if(op[0]=='e')
{
scanf("%lld",&x);
for(ll i=0;i<=n;i++)
ans.mat[i][x]=0;
}
else if(op[0]=='s')
{
scanf("%lld%lld",&x,&y);
for(ll i=0;i<=n;i++)
swap(ans.mat[i][x],ans.mat[i][y]);
}
}
ans=mod_pow(ans,m);
for(ll i=1;i<=n;i++)
printf("%lld%c",ans.mat[0][i],i==n?'\n':' ');
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: