POJ-3735 Training little cats
g i — 给第 i 只猫一颗花生
e i — 吃掉第 i 只猫的所有花生
s i j — 交换第 i 只猫和第 j 只猫的花生
共有n只猫,k次操作,重复这k个操作m次
对于(n+1)*1的矩阵
0 //第一只猫的初始值
0 //2
0 //3
…
0 //n
1 //增量
我们需要动态构造一个N*N的矩阵(N=n+1)
以n=3为例
1 0 0 0 //1
0 1 0 0 //2
0 0 1 0 //3
0 0 0 1 //维护增量 1
最后一列对应每只猫花生的增加量
故
g i 则有mat[i][N]++
e i 则有mat[i][N]=0 和 清空操作前猫自带的花生mat[i][flag[i]]=0
(flag[i]:当前第i行对应上一轮状态中的第flag[i]行)
s i j:
不仅要交换i、j对应的增量swap(mat[i][N],mat[j][N]),
还要交换各标志位以及标志位对应的自身的花生数量
swap(flag[i],flag[j]);
swap([i][flag[i]],[j][flag[i]]);
swap([i][flag[j]],[j][flag[j]]);
#include<iostream>
#include<algorithm>
#include<>
#include<>
using namespace std;
typedef long long ll;
ll N = 105;
struct mat
{
ll a[105][105];
};
mat mul(mat a,mat b)
{
mat c;
memset(,0,sizeof());
for(int i=1;i<=N;i++)
for(int k=1;k<=N;++k)
{
if([i][k]==0)continue;//稀疏矩阵的优化
for(int j=1;j<=N;j++)
{
if([k][j]==0)continue;
[i][j]+=[i][k]*[k][j];
}
}
return c;
}
mat quick(mat a,ll n)
{
mat b;
for(int i=0;i<=N;++i)
for(int j=0;j<=N;++j)
if(i==j)[i][j]=1;
else [i][j]=0;
while(n>0)
{
if(n&1)b=mul(a,b);
a=mul(a,a);
n>>=1;
}
return b;
}
int main()
{
int n,k;
ll m;
char c;
while(cin>>n>>m>>k)
{
if(n==0&&m==0&&k==0)break;
N=n+1;
mat a;
int flag[105];//记录交换后的状态
for(int i=0;i<=N;++i)
for(int j=0;j<=N;++j)
if(i==j){[i][j]=1;flag[i]=i;}
else [i][j]=0;
int l,r;
while(k--){
cin>>c;
if(c=='g'){
cin>>l;
[l][N]++;
}
else if(c=='e'){
cin>>r;
[r][N]=0;
[r][flag[r]]=0;//一开始由于花生初始值是0忽略了还要清空本身
}
else{
cin>>l>>r;
//交换l、r行
swap([l][flag[l]],[r][flag[l]]);
swap([l][flag[r]],[r][flag[r]]);
swap([l][N],[r][N]);
//更新标志
swap(flag[r],flag[l]);
}
}
a=quick(a,m);
for(int i=1;i<N;++i){
cout<<[i][N];
if(i==N-1)cout<<endl;
else cout<<" ";
}
}
return 0;
}