POJ 3735 Training little cats (矩阵快速幂)

传送门

题目大意是给你K串命令和N只猫,问执行M次后每只猫的状况
其中
s 命令是交换两只猫的花生
g 命令是一只猫拿一个花生
e 命令是一只猫吃完他的花生

我们很明显用矩阵快速幂来做这道题

只不过会有一些细节问题,就是数组要用long long 来存,因为程序中没有mod来取余,还有就是可能矩阵中会有很多0,所以时间需要优化,毕竟最大100*100的矩阵相乘是O(n*n*n)复杂度。

代码如下

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;

struct mmmm
{
    LL matrix[105][105];
};

int n,m,k;

mmmm ma_pow(mmmm a,mmmm b)
{
    mmmm c;
    memset(c.matrix,0,sizeof(c.matrix));
    for(int i=0;i<=n;i++){
        for(int k=0;k<=n;k++){
            if(a.matrix[i][k]!=0){//优化时间
                for(int j=0;j<=n;j++){
                    c.matrix[i][j] += a.matrix[i][k]*b.matrix[k][j];
                }
            }
        }
    }
    return c;
}

mmmm solve(mmmm a,int m)
{
    mmmm c;
    memset(c.matrix,0,sizeof(c.matrix));
    for(int i=0;i<=n;i++) c.matrix[i][i] = 1;
    while(m){
        if(m&1) c = ma_pow(c,a);
        a = ma_pow(a,a);
        m >>= 1;
    }
    return c;
}



int main()
{
    while(scanf("%d%d%d",&n,&m,&k)&&(n+k+m)){
        //printf("%d %d %d\n",n,m,k);
        char c;
        mmmm aa;
        memset(aa.matrix,0,sizeof(aa.matrix));
        for(int i=0;i<=n;i++) aa.matrix[i][i] = 1;
        for(int i=0,x,y;i<k;i++){
            getchar();
            scanf("%c",&c);
            //printf("%c \n",c);
            if(c =='g'){
                scanf("%d",&x);
                //printf("%d \n",x);
                aa.matrix[x-1][n]++;
            }else if(c =='e'){
                scanf("%d",&x);
                //printf("%d\n",x);
                memset(aa.matrix[x-1],0,sizeof(aa.matrix[x-1]));
            }else if(c =='s'){
                scanf("%d%d",&x,&y);
                //printf("%d %d\n",x,y);
                for(int i=0;i<=n;i++){
                    swap(aa.matrix[x-1][i],aa.matrix[y-1][i]);
                }
            }
        }
        /*
        for(int i=0;i<=n;i++){
            for(int j=0;j<=n;j++){
                printf("%d ",aa.matrix[i][j]);
            }
            printf("\n");
        }
        */

        mmmm ans = solve(aa,m);

        for(int i=0;i<n;i++){
            printf("%lld%c",ans.matrix[i][n],i==n-1?'\n':' ');
        }
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值