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

来源:互联网 发布:js只选择小时分钟控件 编辑:程序博客网 时间:2024/06/06 09:17

问题

这次的问题是让你找出式子(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*Bmat 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^nmat 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
原创粉丝点击