UVa 10655

祭奠下我又一个wa了20+次的题,(都是泪啊。~~),这个题的也其实就是一个矩阵快速幂,但是写的时候有一些小坑,比如数据都要取long long 的,改了后我还是 wa,其实是结构体的里的矩阵也要ll,然而这个 一直忘记改了,就这样一直wa。。。。。。。。。。。还有就是在重载 * 运算的时候的行列大小要搞对,m*n 的与n*p的相乘,可以得到m*p然后中间的变量k的值就是最大到第一个矩阵的列数或者第二个矩阵的行数。

最后还有一个地方有小坑,就是当p=q=0的时候,不要急着就退出了,因为这个时候a=b=0,那么输出可以是0,不要退出(虽然题目也告诉我要退出,但是就改了这么一个地方测试着交了一发,就会wa掉,= =!)(题目的意思应该是只包含两个0的,如果是0 0 k 这样三个的就继续正常进行咯?!= =?,感觉以后还是好好读题把。)

下面包含着两种写法(另外一个是递归的)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
typedef long long ll;
ll p,q,n;
struct Mat {
    ll mat[5][5];
    int r,c;
    //Mat(int _r,int _c):r(_r),c(_c) {};
};

Mat operator * (Mat a, Mat b) {
    Mat m;
    memset(m.mat, 0, sizeof(m.mat));
    m.r=a.r;
    m.c=b.c;
    int i, j, k;
        for(i = 0; i < m.r; ++i) {
           // if(a.mat[i][k] <= 0)  continue;    //***
            for(j = 0; j < m.c; ++j) {
               // if(b.mat[k][j] <= 0)    continue;    //***
               for(k=0;k<a.c;++k)
                m.mat[i][j] = m.mat[i][j]+a.mat[i][k] * b.mat[k][j];
            }
        }
    return m;
}

Mat operator ^ (Mat a, ll k) {
    Mat m;
    m.r=a.r;
    m.c=a.c;
    int i,j;
    for(i = 0; i < m.r; ++i)
        for(j = 0; j < m.c; ++j)
            m.mat[i][j] = (i == j);
    for(; k; k >>= 1) {
        if(k&1) m = m*a;
        a = a*a;
    }
    return m;
}

Mat multiply(Mat a,Mat b)
 {
     Mat m;
     m.r=a.r;m.c=a.c;
     for(int i=0;i<m.r;++i){
       for(int j=0;j<m.c;++j){
            m.mat[i][j]=0;
                for(int k=0;k<a.c;++k)
                 m.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
         }
     }
     return m;
 }

Mat matrix_pow(Mat m,int n)
 {
    if(n==0){
         m.mat[0][0]=m.mat[1][1]=1;
         m.mat[0][1]=m.mat[1][0]=0;
         return m;
     }
     if(n==1)
         return m;
     Mat res=matrix_pow(m,n/2);
     res=multiply(res,res);
     if(n&1)
         res=multiply(res,m);
     return res;
 }

int main()
{
    while(scanf("%lld%lld%lld",&p,&q,&n)==3)
    {
        if(n==0)
        {
            printf("2\n");
            continue;
        }
         if(n==1)
        {
           printf("%d\n",p);
             continue;
        }
        Mat a;
      a.mat[0][0]=p;
      a.mat[0][1]=-q;
      a.mat[1][0]=1;
      a.mat[1][1]=0;
      a.r=2;a.c=2;
      Mat b;
      b.mat[0][0]=p*p-2*q;
      b.mat[1][0]=p;
      b.r=2;b.c=1;
        ll k=n-2;
        Mat tmp=a^k;
        tmp=tmp*b;
        ll sum=tmp.mat[0][0];
       cout<<sum<<endl;
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值