http://poj.org/problem?id=3735
大致题意:
有n仅仅猫,開始时每仅仅猫有花生0颗,现有一组操作,由以下三个中的k个操作组成:
1. g i 给i仅仅猫一颗花生米
2. e i 让第i仅仅猫吃掉它拥有的全部花生米
3. s i j 将猫i与猫j的拥有的花生米交换
现将上述一组操作循环m次后,问每仅仅猫有多少颗花生?
非常明显,要先构造矩阵。构造一个(n+1)*(n+1)的矩阵a,初始化为单位矩阵。
g i : a[i][n+1] += 1;
e i : a[i][j] = 0;(1 <= j <= n+1)
s i j : swap(a[i][k],a[j][k])(1 <= k <= n+1)
然后矩阵高速幂就ok了。
注意m非常大,k也不小,要用long long .
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)
#define C 240
#define S 20
using namespace std;
const int maxn = 110;
int n,m,k;
struct matrix
{
LL mat[maxn][maxn];
void init()
{
memset(mat,0,sizeof(mat));
for(int i = 1; i <= n+1; i++)
mat[i][i] = 1;
}
}a,b;
matrix mul(matrix a, matrix b)
{
matrix ans;
memset(ans.mat,0,sizeof(ans.mat));
for(int i = 1; i <= n+1; i++)
{
for(int k = 1; k <= n+1; k++)
{
if(a.mat[i][k] == 0) continue;
for(int j = 1; j <= n+1; j++)
ans.mat[i][j] += a.mat[i][k] * b.mat[k][j];
}
}
return ans;
}
matrix pow(matrix a, int nn)
{
matrix ans;
ans.init();
while(nn)
{
if(nn&1)
ans = mul(ans,a);
a = mul(a,a);
nn >>= 1;
}
return ans;
}
int main()
{
char ch[3];
int x,y;
while(~scanf("%d %d %d",&n,&m,&k))
{
if(n == 0 && m == 0 && k == 0) break;
a.init();
memset(b.mat,0,sizeof(b.mat));
b.mat[n+1][1] = 1;
while(k--)
{
scanf("%s",ch);
if(ch[0] == 'g')
{
scanf("%d",&x);
a.mat[x][n+1] += 1;
}
else if(ch[0] == 'e')
{
scanf("%d",&x);
for(int i = 1; i <= n+1; i++)
a.mat[x][i] = 0;
}
else
{
scanf("%d %d",&x,&y);
for(int i = 1; i <= n+1; i++)
swap(a.mat[x][i],a.mat[y][i]);
}
}
a = pow(a,m);
matrix ans = mul(a,b);
for(int i = 1; i <= n; i++)
{
printf("%lld",ans.mat[i][1]);
if(i == n) printf("\n");
else printf(" ");
}
}
return 0;
}