http://poj.org/problem?id=3735
题目大意:重复训练一只猫m轮,在每轮中都有k次操作;有三种不同的操作类型:
1、给第i只猫多一颗豆
2、让第i只猫把它所拥有的都全吃了
3、交换两只猫手中的豆
用矩阵乘法,开一个(n+1)*(n+1)大的数组A。用A.a[0][i]记录第i只猫的实际豆拥有量,则
1、给第i只猫多一颗豆 → A.a[0][i] ++
2、让第i只猫把它所拥有的都全吃了 → for all j , A.a[j][i] = 0
3、交换两只猫a和b手中的豆 → for all i ,swap(A.a[i][a] , A.a[i][b])
这里矩阵乘法有一个优化;
即
for(int i=0;i<n;i++) for(int k=0;k<m;k++) if(a[i][k]) for(int j=0;j<b.m;j++) tmp.a[i][j] += a[i][k]*b.a[k][j];
代码:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 110; struct Matrix { int n , m; ll a[N][N]; Matrix() {} Matrix(int _n,int _m):n(_n),m(_m){}; void intput() { for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&a[i][j]); } Matrix operator + (const Matrix &b) { Matrix tmp = Matrix(n,m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) tmp.a[i][j] = a[i][j] + b.a[i][j]; return tmp; } Matrix operator - (const Matrix &b) { Matrix tmp = Matrix(n,m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) tmp.a[i][j] = a[i][j] - b.a[i][j]; return tmp; } Matrix operator * (const Matrix &b) { Matrix tmp = Matrix(n,b.m); for(int i=0;i<n;i++) for(int j=0;j<b.m;j++) tmp.a[i][j] = 0; for(int i=0;i<n;i++) for(int k=0;k<m;k++) if(a[i][k]) for(int j=0;j<b.m;j++) tmp.a[i][j] += a[i][k]*b.a[k][j]; return tmp; } }; Matrix operator ^ (Matrix a , int p) { Matrix ret = Matrix(a.n,a.m); for(int i=0;i<a.n;i++) for(int j=0;j<a.m;j++) ret.a[i][j] = (i == j ? 1 : 0); while(p) { if(p%2) ret = ret * a; a = a * a; p /= 2; } return ret; } /* Matrix mi(Matrix a , int p) { Matrix tmp = Matrix(a.n,a.m); for(int i=0;i<a.n;i++) for(int j=0;j<a.m;j++) if(i==j) tmp.a[i][j]=1; else tmp.a[i][j]=0; if(p == 0) return tmp; if(p == 1) return a; if(p % 2) tmp = a; Matrix tt = mi(a , p/2); return tt * tt * tmp; }*/ int n , m , k; int main() { while(~scanf("%d%d%d",&n,&m,&k) && n+m+k) { Matrix A = Matrix(n+1,n+1); memset(A.a,0,sizeof(A.a)); for(int i=0;i<=n;i++) A.a[i][i] = 1; char ch[5]; int a , b; while(k--) { scanf("%s",ch); if(ch[0] == 'g') { scanf("%d",&a); A.a[0][a] ++; } else if(ch[0] == 'e') { scanf("%d",&a); for(int i=0;i<=n;i++) A.a[i][a] = 0; } else { scanf("%d%d",&a,&b); for(int i=0;i<=n;i++) swap(A.a[i][a],A.a[i][b]); } } A = A ^ m; printf("%I64d",A.a[0][1]); for(int i=2;i<=n;i++) printf(" %I64d",A.a[0][i]); puts(""); } return 0; }