Description
求
fib(0)|fib(1)|fib(2)|...|fib(n)mod1e9+7
n<=10^10
Solution
因为一直是或,所以我们的答案二进制位的每一位都是1.
那么答案就是fib(n)的位数k,2^(k+1)-1.
那么我们就是要快速求出fib(n)的位数。
当n较小的时候,我们就可以直接求出来了。
当n较大的时候呢?
我们知道,斐波那契数列的第n项的通项公式是:
fib(n)=15√[(1+5√2)n−(1−5√2)n]
而且
limn→∞(1−5√2)n=0
于是当n较大的时候,位数就是
log2(15√(1+5√2)n)
也就是
n∗log2(1+5√2)−log2(5√)
然后就解决了。
Code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef double db;
typedef long long ll;
const int mo=1e9+7;
db f[106];
ll n,ans;
int ty;
ll mi(ll x,ll y) {
ll z=1;
for(;y;y/=2,x=x*x%mo) if (y&1) z=z*x%mo;
return z;
}
int main() {
f[1]=1;fo(i,2,100) f[i]=f[i-1]+f[i-2];
for(scanf("%d",&ty);ty;ty--) {
scanf("%lld",&n);
if (n==0) {printf("0\n");continue;}
if (n<=100) {
int l=log(f[n])/log(2);ans=mi(2,l+1);
printf("%lld\n",ans-1);
continue;
}
ll l=n*log((1+sqrt(5))/2)/log(2)-log(sqrt(5))/log(2);
ans=mi(2,l+1);printf("%lld\n",ans-1);
}
}