CSU 1895 Apache is late again(根号2加1的n次方)

来源:互联网 发布:css布局 书籍 知乎 编辑:程序博客网 时间:2024/06/04 18:24

题目:

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

这个题目主要是代数运算,有2类方法,一类是一元递推,一类是二元递推

我用的是一元递推的方法,如下:


接下来就直接根据这个式子求出m就可以了。

不过因为n很大,所以肯定不是用组合数,而是用递推。


虽然我们要求的是bn,但是bn是非齐次线性递推,没法直接矩阵快速幂,而an是齐次线性递推,可以用矩阵快速幂。

需要注意的是从an转化到bn需要除以4,所以需要用到逆元


这样,答案便出来了。

代码:

#include<iostream>using namespace std;long long l[4]={6,100000006,1,0},l1[4],ans[4],p=100000007,p11=50000004;void g(long long *p1,long long *p2,long long *p3){p3[0]=(p1[0]*p2[0]+p1[1]*p2[2])%p;p3[1]=(p1[0]*p2[1]+p1[1]*p2[3])%p;p3[2]=(p1[2]*p2[0]+p1[3]*p2[2])%p;p3[3]=(p1[2]*p2[1]+p1[3]*p2[3])%p;}void f(long long n){if(n==0){ans[0]=ans[3]=1,ans[1]=ans[2]=0;return;}f(n/2);for(int i=0;i<4;i++)l1[i]=ans[i];g(l1,l1,ans);if(n%2==0)return;for(int i=0;i<4;i++)l1[i]=ans[i];g(l1,l,ans);}int main(){long long n,k;while(cin>>n){if(n>0){f(n-1);k=(ans[0]*6+ans[1]*2)%p;cout<<((k*p11)%p+1)*p11%p<<endl;}if(n==0)cout<<1<<endl;if(n<0)cout<<"No\n";}return 0;}

如果用二元递推的话会更简单。


0 0
原创粉丝点击