hdu 4965 Fast Matrix Calculation

hdu 4965 Fast Matrix Calculation

给出n*k的矩阵A k*n的矩阵B 4<=n<=1000  2<=k<=6  然后求A*B得到的新矩阵的n*n次幂 然后矩阵中所有元素%6 

求出最后矩阵中所有元素的值

没想到  到了1000  结构体中开1010*1010的数组就不行了 然后始终保存 无法运行

这题其实思路很简单 就是矩阵快速幂

可以注意到 k的值很小 所以通过转化来将计算的矩阵转化为k*k的矩阵

(A*B)*(A*B)*(A*B)*(A*B)*(A*B)*……(A*B)括号内的值相乘n*n次

矩阵乘法的结合律可以将此转化为A*(B*A)*(B*A)*(B*A)*(B*A)*……*(B*A)*B  括号内的值相乘n*n-1次 

这样就可以避免结构体内数组太大的问题了。。。代码很简单 主要要注意矩阵乘法循环内的条件

代码如下:

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>

#define eps 1e-8
#define op operator
#define mod  6
#define MAXN  100100

#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define FOV(i,a,b)  for(int i=a;i>=b;i--)
#define REP(i,a,b)  for(int i=a;i<b;i++)
#define REV(i,a,b)  for(int i=a-1;i>=b;i--)
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

int n,k;

struct matrix
{
    int a[10][10];
};

matrix ori,res;

void init()
{
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<k;i++)
            res.a[i][i]=1;
}

matrix multiply(matrix x,matrix y)
{
//    cout<<"aaa"<<endl;
    matrix temp;
    MEM(temp.a,0);
    for(int i=0;i<k;i++)
    {
        for(int j=0;j<k;j++)
        {
            for(int m=0;m<k;m++)
            {
                temp.a[i][j]+=(x.a[i][m]*y.a[m][j]);
                temp.a[i][j]%=mod;
            }
        }
    }
    return temp;
}

void calc(int num)
{
//    cout<<"aaa"<<endl;
    while(num)
    {
        if(num&1)
            res=multiply(ori,res);
        num>>=1;
        ori=multiply(ori,ori);
    }
//    for(int i=0;i<k;i++)
//    {
//        for(int j=0;j<k;j++)
//            cout<<res.a[i][j]<<"\t";
//        cout<<endl;
//    }
}

int p[1010][1010],q[1010][1010];
int ans1[1010][1010],ans2[1010][1010];

int main()
{
freopen("ceshi.txt","r",stdin);
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(n==0&&k==0)  break;
        init();
        MEM(ori.a,0);
        for(int i=0;i<n;i++)
            for(int j=0;j<k;j++)
                scanf("%d",&p[i][j]);
        for(int i=0;i<k;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&q[i][j]);
//        cout<<"111111111111111111"<<endl;
        for(int i=0;i<k;i++)
            for(int j=0;j<k;j++)
        {
            for(int m=0;m<n;m++)
                ori.a[i][j]+=q[i][m]*p[m][j];
//            cout<<"1111"<<endl;
        }
//        for(int i=0;i<n;i++)
//        {
//            for(int j=0;j<n;j++)
//            {
//                cout<<ori.a[i][j]<<" ";
//            }
//            cout<<endl;
//        }
//        cout<<n*n<<endl;
        calc(n*n-1);
        MEM(ans1,0);  MEM(ans2,0);
        for(int i=0;i<n;i++)
            for(int j=0;j<k;j++)
                for(int m=0;m<k;m++)
                {
                    ans1[i][j]+=p[i][m]*res.a[m][j];
                    ans1[i][j]%=6;
                }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                for(int m=0;m<k;m++)
        {
            ans2[i][j]+=ans1[i][m]*q[m][j];
            ans2[i][j]%=6;
        }
        int sum=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
        {
            sum+=(ans2[i][j]%mod);
        }
        printf("%d\n",sum);
    }
    return 0;
}
</span>

有时间了 也要写下用stl存储的方法!!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值