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

poj-3735-Training little cats-矩阵快速幂

2016-05-29 17:57 513 查看
Link:http://poj.org/problem?id=3735

Training little cats

Time Limit: 2000MS      Memory Limit: 65536K
Total Submissions: 11954        Accepted: 2951


Description

Facer's pet cat just gave birth to a brood of little cats. Having considered the health of those lovely cats, Facer decides to make the cats to do some exercises. Facer has well designed a set of moves for his cats. He is now asking you to supervise the cats to do his exercises. Facer's great exercise for cats contains three different moves:
g i : Let the ith cat take a peanut.
e i : Let the ith cat eat all peanuts it have.
s i j : Let the ith cat and jth cat exchange their peanuts.
All the cats perform a sequence of these moves and must repeat it m times! Poor cats! Only Facer can come up with such embarrassing idea.
You have to determine the final number of peanuts each cat have, and directly give them the exact quantity in order to save them.


Input

The input file consists of multiple test cases, ending with three zeroes "0 0 0". For each test case, three integers n, m and k are given firstly, where n is the number of cats and k is the length of the move sequence. The following k lines describe the sequence.
(m≤1,000,000,000, n≤100, k≤100)


Output

For each test case, output n numbers in a single line, representing the numbers of peanuts the cats have.


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


Source

PKU Campus 2009 (POJ Monthly Contest – 2009.05.17), Facer


思路:

这个题我们看到m非常大,并且应该是牵涉到线性变化的,故我们自然而然的联想到矩阵快速幂,但是这个题比较难的便是矩阵的构造,因为一开始有n个小猫,我们可以想到nXn的矩阵,那么对于每个小猫有用的是1Xn矩阵,但是这样的话初始是矩阵为零矩阵,无法使用矩阵乘法由此我们修改矩阵为(n+1)X(n+1)矩阵,我们以此题测试数据为例。
我们默认从0开始!!!!!——————!!!!!
开始时
|1 0 0 0|
|0 0 0 0|
|0 0 0 0|
|0 0 0 0|
我们找一个单位矩阵,用于记录变换
|1 0 0 0|
|0 1 0 0|
|0 0 1 0|
|0 0 0 1|
如果给第一只小猫一个peanut的话变换矩阵变成
|1 1 0 0|
|0 1 0 0|
|0 0 1 0|
|0 0 0 1|
连续给第二个小猫两次的话则依次为
|1 1 1 0|
|0 1 0 0|
|0 0 1 0|
|0 0 0 1|

|1 1 2 0|
|0 1 0 0|
|0 0 1 0|
|0 0 0 1|

交换1,2小猫的peanut则相当于变换矩阵的对应1列和2列交换
|1 2 1 0|
|0 0 1 0|
|0 1 0 0|
|0 0 0 1|
清空2猫的peanut则相当于变换矩阵的2列化为0
|1 1 0 0|
|0 1 0 0|
|0 0 0 0|
|0 0 0 1|
综上a猫加一个peanut,变换矩阵M0a++;
a猫清空peanut,变换矩阵a列化为0;
a,b猫交换,a列与b列值交换

本题另一个精彩部分就是对于稀疏矩阵的乘法


代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn(105);
int n;
struct matrix
{
long long mat[maxn][maxn];
void zero()
{
for(int i=0; i<=n; i++)
{
for(int j=0; j<=n; j++)
{
this->mat[i][j]=0;
}
}
}
void unit()
{
zero();
for(int i=0; i<=n; i++)
this->mat[i][i]=1;
}
matrix operator * (const matrix &a)const
{
matrix res;
res.zero();
for(int k=0; k<=n; k++)
{
for(int i=0; i<=n; i++)
{
if(this->mat[i][k])
{
for(int j=0; j<=n; j++)
{
res.mat[i][j]+=this->mat[i][k]*a.mat[k][j];
}
}
}
}
return res;
}
matrix operator ^(int k)const
{
matrix res;
matrix B=*this;
res.unit();
while(k)
{
if(k&1)
res=res*B;
k>>=1;
B=B*B;
}
return res;
}

};

int main()
{
int m,k;
matrix start;
matrix operation;

while(scanf("%d%d%d",&n,&m,&k),n||m||k)
{
start.zero();
start.mat[0][0]=1;
char cmd;
operation.unit();
int a,b;
while(k--)
{
getchar();
cmd=getchar();
switch(cmd)
{
case 'g':
scanf("%d",&a);
operation.mat[0][a]++;
break;
case 'e':
scanf("%d",&a);
for(int i=0; i<=n; i++)
operation.mat[i][a]=0;
break;
default:
scanf("%d%d",&a,&b);
for(int i=0; i<=n; i++)
swap(operation.mat[i][a],operation.mat[i][b]);
break;
}
}
start=start*(operation^m);
for(int i=1; i<n; i++)
cout<<start.mat[0][i]<<" ";
cout<<start.mat[0]
<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息