Fib[0]=0,Fib[1]=1,Fib[n]=Fib[n-1]+Fib[n-2] if n>1.
定义索函数Sor(n)=Fib[0]| Fib[1] |Fib[2]|…|Fib[n].
给定整数n,要求计算Sor(n)%1,000,000,007(1e9+7).
Input
第1行:给出一个整数T,表示有T组数据。(1<=T<=10000) 第2行到T+1行,每行一个整数n。(0<=n<=10^10)
Output
对于每个测试用例,输出结果占一行。
Input示例
2 1 2
Output示例
1 1
思路:
因为是或运算,那么将其Sor(n)转化为二进制,每一位上的值均应该为1,那么我们只需要求出二进制的位长,便可以求得Sor(n)。
对于斐波那契数列数列有:
此时求其以2为底的对数,无法去掉n次幂,很难进行进一步化简,我们继续考虑:
当n趋近于无穷大时:
的值趋近于0,
即此时求出Sor(n)转化为二进制时的长度为:
log2(15
log2(15
进行化简得:
可以O(1)求出Sor(n)的位长len,通过快速幂求出 2^(len+1)的值后减去一得到Sor(n)的数值。
蛮有意思的一道题目。
#include <stdio.h> #include <math.h> #define MAXSIZE 90 #define INF 0x3f3f3f3f #define LL long long const int mod = 1e9+7; double f[MAXSIZE]; LL Pow(LL a,LL n) { LL ans = 1; while(n) { if(n & 1) { ans = (ans*a)%mod; } a = (a*a)%mod; n >>= 1; } return ans%mod; } LL Solve(LL n) { LL ans,len; if(n < MAXSIZE) { len = log(f[n])/log(2.0); } else len = n*log((1+sqrt(5.0))/2.0)/log(2.0) - log(sqrt(5.0))/log(2.0); ans = Pow(2,len+1); return ans; } int main() { f[0] = 0; f[1] = 1; f[2] = 1; for(int i=3;i<MAXSIZE;i++) { f[i] = f[i-1] + f[i-2]; } int T; LL n; scanf("%d",&T); while(T--) { scanf("%lld",&n); if(n==0) { printf("0 "); continue; } LL ans = Solve(n); printf("%lld ",ans-1); } return 0; }