hdu2256

点击打开hdu 2256

转载地址:http://blog.csdn.net/chenguolinblog/article/details/10212567

思路: 矩阵快速幂

分析:

1 题目要求的是(sqrt(2)+sqrt(3))^2n %1024向下取整的值

 

 

3 这里很多人会直接认为结果等于(an+bn*sqrt(6))%1024,但是这种结果是错的,因为这边涉及到了double,必然会有误差,所以根double有关的取模都是错误的思路


代码:

#include<cmath>  
#include<cstdio>  
#include<cstring>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
  
const int MOD = 1024;  
const int N = 2;  
  
struct Matrix{  
    int mat[N][N];  
    Matrix operator*(const Matrix& m)const{  
        Matrix tmp;  
        for(int i = 0 ; i < N ; i++){  
            for(int j = 0 ; j < N ; j++){  
                tmp.mat[i][j] = 0;  
                for(int k = 0 ; k < N ; k++){  
                    tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%MOD;  
                    tmp.mat[i][j] %= MOD;  
                }  
            }  
        }  
        return tmp;  
    }  
};  
  
int Pow(Matrix &m , int k){  
    if(k == 1)  
        return 9;  
    k--;  
    Matrix ans;  
    memset(ans.mat , 0 , sizeof(ans.mat));  
    for(int i = 0 ; i < N ; i++)  
        ans.mat[i][i] = 1;  
    while(k){  
        if(k&1)  
            ans = ans*m;  
        k >>= 1;  
        m = m*m;  
    }  
    int x = (ans.mat[0][0]*5+ans.mat[0][1]*2)%MOD;  
    return (2*x-1)%MOD;  
}  
  
int main(){  
    int cas , n;  
    Matrix m;  
    scanf("%d" , &cas);  
    while(cas--){  
        scanf("%d" , &n);   
        m.mat[0][0] = 5 ; m.mat[1][1] = 5;  
        m.mat[1][0] = 2 ; m.mat[0][1] = 12;  
        printf("%d\n" , Pow(m , n));  
    }  
}  

下边是自己的代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int mod=1024;
int n;
struct mat
{
    long long mm[2][2];
};
mat operator*(mat a,mat b)
{
    mat c;
    memset(c.mm,0,sizeof(c.mm));
    for(int i=0; i<2; i++)
        for(int j=0; j<2; j++)
            for(int k=0; k<2; k++)
            {
                c.mm[i][j]+=a.mm[i][k]*b.mm[k][j];
                c.mm[i][j]%=mod;
            }
    return c;
}
void pow(int n)
{
    if(n==1)
        printf("9\n");
    else
    {
        n--;
        mat res,ans;
        memset(ans.mm,0,sizeof(ans.mm));
        for(int i=0; i<2; i++)
            ans.mm[i][i]=1;
        res.mm[0][0]=5;
        res.mm[0][1]=2;
        res.mm[1][0]=12;
        res.mm[1][1]=5;
        while(n)
        {
            if(n%2==1)
                ans=ans*res;
            res=res*res;
            n/=2;
        }
    int x=(ans.mm[0][0]*5+ans.mm[0][1]*12)%mod;
    printf("%d\n",(2*x-1)%mod);
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        pow(n);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值