C++ 如何用A,B<计算斐波那契(A)模B=10^18英寸C++;(g+;+;)
例如,A=10^17,B=10^17(=mod)c-=mod; d=(a*a+b*b);/*F(2n+1)*/ 而(d>=mod)d-=mod; 如果(n%2==0){ ans[0]=c; ans[1]=d; } 否则{ ans[0]=d; ans[1]=c+d; } } int main(){ int T=1000; 长n; 而(T--){ scanf(“%lld%lld”、&n和&mod); long-long-ans[2]={0}; 快速fib(n,ans); printf(“%lld\n”,ans[0]); } 返回0; }C++ 如何用A,B<计算斐波那契(A)模B=10^18英寸C++;(g+;+;),c++,algorithm,math,g++,implementation,C++,Algorithm,Math,G++,Implementation,例如,A=10^17,B=10^17(=mod)c-=mod; d=(a*a+b*b);/*F(2n+1)*/ 而(d>=mod)d-=mod; 如果(n%2==0){ ans[0]=c; ans[1]=d; } 否则{ ans[0]=d; ans[1]=c+d; } } int main(){ int T=1000; 长n; 而(T--){ scanf(“%lld%lld”、&n和&mod); long-long-ans[2]={0}; 快速fib(n,ans); printf(“%lld\n
使用uu float128,我无法有效地实现模运算,a、b、c、d必须存储128位数据。计算不需要任何浮点类型。只能使用
long
类型。首先,您需要一个将两个long
数(小于10^18
)乘以模B
的函数。这可以通过类似的方法完成:
其次,您需要将模运算添加到几乎所有的算术运算中。当(c>=mod)c-=mod时,您肯定需要将这些循环替换为(它们可能非常慢),在相应的操作中添加%mod
用\uuu float\u 128
替换为long
并使用适当的模运算的代码:
您可以做的另一件事是使用(如注释中所述)Boost.Multiprecision
或非标准的\u int128
类型(如果支持),而不是复杂乘法的long
类型
另外,你可以使用一个稍微不同的方法(但实际上使用的是相同的数学),这对我来说似乎更明显——斐波那契数矩阵公式
要计算矩阵的N
th次方,您可以通过对所有运算进行平方运算来使用幂运算,即模B
“Fibonnacci(A)超过长整型”的可能重复项--不相关,您只需首先计算模B即可。@harold+1:然后,这是mathoverflow的问题。可能重复或您可以选择其他算法清晰的解释(但无代码):这与我在帖子中提到的斐波那契快速倍增算法的问题相同。问题更多的是我可以用来计算它的类型。我已经看到了uu float128,但是我不认为我可以用这个float实现所有的int变量。假设x86_64,\uu int128
将使乘法更容易。或者使用Boost.Multiprecision类型。注意:这与问题中提供的快速倍增算法基本相同,性能相同。@JamesKPolk,没错。问题的早期版本没有包含任何代码或实现细节,我提出的矩阵方法对我个人来说似乎更为明显。这是另一个有趣的公式。
#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;
}
long long multiply(long long a, long long b, long long M) {
long long res = 0;
long long d = a;
while (b > 0) {
if (b & 1) {
res = (res + d) % M;
}
b /= 2;
d = (d + d) % M;
}
return res;
}