hdoj.2256 Problem of Precision【矩阵快速幂】 2015/08/18

Problem of Precision

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1043    Accepted Submission(s): 612


Problem Description

 

Input
The first line of input gives the number of cases, T. T test cases follow, each on a separate line. Each test case contains one positive integer n. (1 <= n <= 10^9)
 

Output
For each input case, you should output the answer in one line.
 

Sample Input
  
  
3 1 2 5
 

Sample Output
  
  
9 97 841
 

Source

注:( √2+√3)^2n = ((√2+√3)^2)^n = (5+2√6)^n
由于√6消除不掉,设(5+2√6)^n = an+bn√6
则第n+1项 a(n+1) + b(n+1)√6 = (5+2√6)*(an + bn√6) = (5an+12bn) + (2an+5bn)√6
即a(n+1) = 5an+12bn,,b(n+1) = 2an+5bn
可由此构建矩阵
| 5 12 | *| an | = | a(n+1) |
| 2 5   |   | bn |    | b(n+1) |
再 (5+2√6)^n 向下取整   首先double不可取余操作
故令 (5+2√6)^n + (5-2√6)^n = (an+bn√6) + (an-bn√6) = 2an
又(5-2√6≈ 0.101020...  (5-2√6)^n 无限趋近于 0   
所以(5+2√6)^n 向下取整   即为 2an-1
#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

struct node{
    int m[2][2];
}res,per;

int t,n;
const int m = 1024;

void init(){
    per.m[0][0] = per.m[1][1] = 1;
    per.m[0][1] = per.m[1][0] = 0;
    res.m[0][0] = res.m[1][1] = 5;
    res.m[0][1] = 12;
    res.m[1][0] = 2;
}

node mutil(node a,node b){
    int i,j,k;
    node c;
    for( i = 0 ; i< 2 ; ++i )
        for( j = 0 ; j < 2 ; ++j ){
            c.m[i][j] = 0;
            for( k = 0 ; k < 2 ; ++k )
                c.m[i][j] += (a.m[i][k] * b.m[k][j])%m;
            c.m[i][j] %= m;
        }
    return c;
}

void modefy( int k ){
    node ans = per,p = res;
    while( k ){
        if( k&1 ) ans = mutil(ans,p);
        p = mutil(p,p);
        k>>=1;
    }
//    for( int i = 0 ; i < 2 ; ++i )
//        printf("----  %d  %d\n",ans.m[i][0],ans.m[i][1]);
    printf("%d\n",(10*ans.m[0][0] + 4*ans.m[0][1] - 1) % m);
}

int main(){
    init();
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        if( n == 1 )
            printf("9\n");
        else modefy(n-1);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值