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√(1+5√2)n)
log2(15√(1+5√2)n)
进行化简得:
可以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 longconst 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);}elselen = 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\n");continue;}LL ans = Solve(n);printf("%lld\n",ans-1);}return 0; }