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

POJ 3735 Training little cats(矩阵乘法)

2017-02-08 16:36 344 查看
【题目链接】 http://poj.org/problem?id=3735

【题目大意】

  有一排小猫,给出一系列操作,包括给一只猫一颗花生,
  让某只猫吃完所有的花生以及交换两只猫的花生,
  求完成m次操作集合之后每只猫的花生数量

【题解】

  创建一个1*(n+1)的初始矩阵,
  对于给第i只猫一个花生就相当于乘上修改了A[0][i]的单位矩阵
  如给第一只猫一个花生就修改A[0][1]为1
  得到:
    1 1 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 1
  然后我们用初始矩阵去乘这个矩阵,就完成了加的操作
  对于让第i只猫吃完所有的花生,我们将A[i][i]修改为0
  如让第三只猫吃完花生,那么就相当于将A[3][3]改为0
  得到
    1 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 0
  然后我们用初始矩阵去乘这个矩阵,就完成了清零的操作
  对于交换花生的操作,我们交换单位矩阵的第x和y行,然后相乘即可
  比如交换第一只猫和第三只猫的花生,我们就得到
    1 0 0 0
    0 0 0 1
    0 0 1 0
    0 1 0 0
  乘到初始矩阵上即可
  我们发现经过这些操作,我们最后会得到一个操作集合的矩阵表达
  而这些操作的变换其实不用整个乘上矩阵,只要直接修改单位矩阵的部分值即可
  第一种操作的影响可以转化为A[0][x]++
  第二种操作的影响可以转化为A[0~n][x]=0
  第三种操作的影响可以转化为i_0^n swap(A[i][x],A[i][y])
  那么我们直接计算转置矩阵即可。

【代码】

#include <cstdio>
#include <vector>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
typedef long long LL;
typedef vector<vector<LL> > mat;
LL n,m,k,x,y;
char op[10];
mat mul(mat &A,mat &B){
mat C(A.size(),vector<LL>(B[0].size()));
rep(i,A.size())rep(k,B.size())if(A[i][k]){
rep(j,B[0].size())C[i][j]+=A[i][k]*B[k][j];
}return C;
}
mat pow(mat A,LL n){
mat B(A.size(),vector<LL>(A.size()));
rep(i,A.size())B[i][i]=1;
for(;n;n>>=1){if(n&1)B=mul(B,A);A=mul(A,A);}
return B;
}
int main(){
while(scanf("%lld%lld%lld",&n,&m,&k),n+m+k){
mat A(n+1,vector<LL>(n+1));
rep(i,n+1)A[i][i]=1;
while(k--){
scanf("%s",&op);
if(op[0]=='g'){
scanf("%lld",&x);
A[0][x]++;
}else if(op[0]=='e'){
scanf("%lld",&x);
rep(i,n+1)A[i][x]=0;
}else{
scanf("%lld%lld",&x,&y);
rep(i,n+1)swap(A[i][x],A[i][y]);
}
}if(m){
A=pow(A,m);
printf("%lld",A[0][1]);
for(int i=2;i<=n;i++)printf(" %lld",A[0][i]);
puts("");
}else{
printf("0");
rep(i,n-1)printf(" 0");
puts("");
}
}return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: