我正在为自己做一个非常复杂的任务,在给定n个段时,我必须计算最大可能的序列数。
我发现加泰罗尼亚数字代表了这个序列,我让它适用于n <= 32。我得到的结果应该计算为1.000.000.007。我遇到的问题是“q”和“p”对于一个很长的int而言变得很大而且我在分割“q”和“p”之前不能只修改1.000.000.007,因为我会得到不同的结果。
我的问题是,是否有一种非常有效的方法来解决我的问题,或者我是否必须考虑以不同的方式存储值? 我的限制如下: - 仅限stdio.h / iostream - 只有整数 - n <= 20.000.000 - n> = = 2
#include <stdio.h>
long long cat(long long l, long long m, long long n);
int main(){
long long n = 0;
long long val;
scanf("%lld", &n);
val = cat(1, 1, n / 2);
printf("%lld", (val));
return 0;
}
long long cat(long long q, long long p, long long n){
if (n == 0) {
return (q / p) % 1000000007;
}
else {
q *= 4 * n - 2;
}
p *= (n + 1);
return cat(q, p, n - 1);
}
答案 0 :(得分:4)
为了有效地解决这个问题,你需要使用modular arithmetic,modular inverses代替除法。
在没有溢出的情况下证明(a * b) % c == ((a % c) * b) % c
很简单。如果我们只是乘以,我们可以在每一步取结果mod 1000000007并始终保持在64位整数的范围内。问题在于分裂。 (a / b) % c
不一定等于((a % c) / b) % c
。
为了解决除法问题,我们使用模块化逆。对于具有a
素数和c
的整数c
和a % c != 0
,我们总能找到b
整数a * b % c == 1
。这意味着我们可以使用乘法作为除法。对于d
,a
可整除的任何整数(d * b) % c == (d / a) % c
。这意味着((d % c) * b) % c == (d / a) % c
,因此我们可以减少中间结果mod c而不会破坏我们的分裂能力。
我们想要计算的数字是(x1 * x2 * x3 * ...) / (y1 * y2 * y3 * ...) % 1000000007
形式。我们可以改为计算x = x1 % 1000000007 * x2 % 1000000007 * x3 % 1000000007 ...
和y = y1 % 1000000007 * y2 % 1000000007 * y3 % 1000000007 ...
,然后使用extended Euclidean algorithm计算z
的模块逆y
并返回(x * z) % 1000000007
。
答案 1 :(得分:2)
如果您正在使用gcc或clang和64位目标,则存在__int128 type。这为您提供了额外的位,但显然只有一点。
最有可能解决此类问题的最简单方法是使用&#34; bignum&#34;库,即处理任意大数字表示和算术运算的库。可以说是最受欢迎的开源示例是libgmp - 您应该能够轻松地使用该算法。它还调整了高性能标准。
显然,你可以自己重新实现这一点,将你的数字表示为例如一定大小的整数数组。您必须实现用于执行基本算术的算法,例如+, - ,*,/,%。如果你想做一个很好的学习体验,但是如果你只想专注于你想要实现的算法,那么使用libgmp并不羞耻。