矩阵快速幂-- 挑战程序设计

问题

这次的问题是让你找出式子(3 + √5)n结果的小数点前三位数字。
例如:当n = 5时,(3 + √5)n = 3935.73982... 那么答案是 935。
当n = 2时,(3 + √5)n = 2.4164079... 那么答案是 027。

输入
第一行是测试用例的数目T。紧接着是T个测试用例,一行一个。每一个测试用例包含一个正整数n。

输出
对于每一个测试用例,你应输出:
Case #X: Y
X表示第几个测试用例,Y表示(3 + √5)n结果的最后三位整数数字。如果结果的整数少于3位则补零,保证Y总是3位。

约束

1 <= T <= 100
小测试数据
2 <= n <= 30
大测试数据
2 <= n <= 2000000000

例子
输入
2
5
2
输出
Case #1: 935
Case #2: 027

矩阵乘法运算:

在计算机中,一个矩阵说穿了就是一个二维数组。一个n行m列的矩阵可以乘以一个m行p列的矩阵,得到的结果是一个n行p列的矩阵,其中的第i行第j列位置上的数等于前一个矩阵第i行上的m个数与后一个矩阵第j列上的m个数对应相乘后所有m个乘积的和。比如,下面的算式表示一个2行2列的矩阵乘以2行3列的矩阵,其结果是一个2行3列的矩阵。其中,结果的那个4等于2*2+0*1:

  

code;

#include<iostream>
#include<cstdio>
#include<vector>//分配动态数组
#include<cstring>
#include<algorithm>
#include<utility>
#include<queue>
using namespace std;
typedef vector<int> vec;一维数组
typedef vector<vec> mat;嵌套二维数组
typedef long long ll;
const int M=10000;
//计算A*B
mat mul(mat& A,mat& B)//两个矩阵相乘
{
    mat C(A.size(),vec(B[0].size()));//第一个矩阵的行 第二个矩阵的列
    for(int i=0;i<A.size();i++){
        for(int k=0;k<C.size();k++){
            for(int j=0;j<B.size();j++){
                C[i][j]=(C[i][j]+A[i][k]*B[k][j])%M;
            }
        }
    }
    return C;
}
//计算A^n
mat pow(mat A,ll n)
{
    mat B(A.size(),vec(A.size()));元素个数
    for(int i=0;i<A.size();i++){
        B[i][i]=1;数组B初始化为1
    }
    while(n>0){
        if(n&1) B=mul(B,A);
        A=mul(A,A);
        n>>=1;//除以2
    }
    return B;
}

const int Mod=1000;

int n;
void solve()
{
    mat A(2,vec(2,0));//vec(2,0)两个元素,初始化为0
    A[0][0]=3;A[0][1]=5;
    A[1][0]=1;A[1][1]=3;
    A=pow(A,n);
    printf("%03d\n",(A[0][0]*2+Mod-1)%Mod);
}
int main()
{
    int t,kase=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        printf("Case #%d: ",++kase);
        solve();
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值