CSU->1895: Apache is late again

1895: Apache is late again

             Time Limit: 1 Sec     Memory Limit: 128 Mb    

Description

Apache is a student of CSU. There is a math class every Sunday morning, but he is a very hard man who learns late every night. Unfortunate, he was late for maths on Monday. Last week the math teacher gave a question to let him answer as a punishment, but he was easily resolved. So the math teacher prepared a problem for him to solve. Although Apache is very smart, but also was stumped. So he wants to ask you to solve the problem. Questions are as follows: You can find a m made (1 + sqrt (2)) ^ n can be decomposed into sqrt (m) + sqrt (m-1), if you can output m% 100,000,007 otherwise output No.

Input

There are multiply cases. Each case is a line of n. (|n| <= 10 ^ 18)

Output

Line, if there is no such m output No, otherwise output m% 100,000,007.

Sample Input

2

Sample Output

9

Hint

Source

中南大学第十一届大学生程序设计竞赛

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1895

题解:由于n很大,直接求解会WA,本题需要利用矩阵快速幂,具体看代码:

#include<iostream>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int Mod=100000007;

struct maxtri{
    ll v[2][2];
    maxtri (){
        memset(v,0,sizeof(v));
    }
    maxtri operator *(const maxtri &m){
        maxtri tmp;
        for(int i=0;i<2;i++){
            for(int j=0;j<2;j++){
                for(int k=0;k<2;k++){
                    tmp.v[i][j]+=(v[i][k]*m.v[k][j])%Mod;
                }
            } 
        }
        return tmp;
    }
}; 
maxtri M,E,ans;     //M即为矩阵,E即为单位矩阵,ans为解 
void Init(){
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            if(i==j){
                E.v[i][j]=1;
            }
        }
    }
    M.v[0][0]=2;M.v[0][1]=1;
    M.v[1][0]=1;M.v[1][1]=0;
}   
maxtri quickPow(maxtri m,ll n){
    maxtri tmp=E;
    while(n){
        if(n&1){
            tmp=tmp*m;
        }
        m=m*m;
        n>>=1;
    }
    return tmp;
}
int main(){
    ll n;
    while(scanf("%lld",&n)!=EOF){
        Init();
        if(n<0){
            printf("No\n");
        }
        else if(n==0){
            printf("1\n");
        }
        else if(n==1){
            printf("2\n");
        }
        else if(n==2){
            printf("9\n");
        }
        else{
            ans=quickPow(M,n-2);
            ll aa=(3*ans.v[0][0]+ans.v[0][1]*1)%Mod;
            if(n&1){
                printf("%lld\n",(ll)((aa*aa)%Mod+1)%Mod);
            }
            else{
                printf("%lld\n",(ll)(aa*aa)%Mod);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值