【发布时间】:2017-09-27 13:34:33
【问题描述】:
例如,A=10^17, B=10^17 (
通常,在上面的算法中,计算 F(2n) 和计算 F(2n+1) 的计算超过了 long long int 类型,我们不能在其中使用模计算。
我所说的计算它的最佳算法是斐波那契快速加倍:
F(0) = 0, F(1) = 1。
F(2n) = F(n)(2*F(n+1) – F(n))。
F(2n + 1) = F(n)2 + F(n+1)2.
你知道在新的 C++14(g++8.3.0 或 llvm-clang C++)中使用一些类型来避免溢出吗?
我试过 __float128 比 long double 好,但没有成功。 (参见上面的 g++ 代码)
我听说存在 __int128 和 __int256 没有 printf 的可能性,但我没有尝试过。
它们在 g++ 8.3.0 中是否可用,或者是否有其他快速方法来处理 128 位整数来进行您能想到的中间计算?
(时间性能很重要)
#include <bits/stdc++.h>
using namespace std;
__float128 a,b,c,d;
long long mod;
void fast_fib(long long n,long long ans[]){
if(n == 0){
ans[0] = 0;
ans[1] = 1;
return;
}
fast_fib((n/2),ans);
a = ans[0]; /* F(n) */
b = ans[1]; /* F(n+1) */
c = 2*b - a;
if(c < 0) c += mod;
c = (a * c); /* F(2n) */
while(c>=mod)c-=mod;
d = (a*a + b*b); /* F(2n + 1) */
while(d>=mod)d-=mod;
if(n%2 == 0){
ans[0] = c;
ans[1] = d;
}
else{
ans[0] = d;
ans[1] = c+d;
}
}
int main(){
int T=1000;
long long n;
while(T--){
scanf("%lld %lld",&n,&mod);
long long ans[2]={0};
fast_fib(n,ans);
printf("%lld\n", ans[0]);
}
return 0;
}
使用 __float128 我无法有效地实现模数,a、b、c、d 必须存储 128 位数据。
【问题讨论】:
-
“Fibonnacci(A) 超过 long long int 类型”——无关紧要,您只需首先对 B 取模即可。
-
@harold +1:然后,这是 mathoverflow 的问题。
-
Huge fibonacci modulo m C++ 的可能重复项,或者您可以选择其他算法
-
清晰的解释(但没有代码):stackoverflow.com/questions/40556760/…
标签: c++ algorithm math g++ implementation