【发布时间】:2018-08-11 17:02:54
【问题描述】:
这个问题实际上来自一个名为 codechef 的竞争性编程网站。
问题如下。
给定整数 A、B 和 N,你应该计算 A^N+B^N 的 GCD 和 |A-B|。 (假设任何正整数 a 的 GCD(0,a)=a)。从此 数字可能非常大,以 1000000007 (109+7) 为模计算。
完整的问题是here
值的限制如下:
1
1
B
当 A、B、N 的值非常大时,我的解决方案通过了第一个子任务但第二个失败。
这是我的解决方案:
#include <bitset>
#include <iostream>
using std::bitset;
using std::cin;
using std::cout;
typedef unsigned long long ull;
constexpr size_t bit_size = sizeof(ull) * 8;
ull modular_exponetiation(ull a, bitset<bit_size> n, ull mod) {
ull c = 0;
ull d = 1;
for (int t = n.size() - 1; t >= 0; t--) {
c *= 2;
d = ((d % mod) * (d % mod)) % mod; //(d*d)%mod
if (n[t] == 1) {
c++;
d = ((d % mod) * (a % mod)) % mod; //(d*a)%mod
}
}
return d;
}
ull euclid_gcd(ull a, ull b) {
if (b == 0)
return a;
else
return euclid_gcd(b, a % b);
}
int main() {
int test;
cin >> test;
while (test--) {
ull a, b, n;
cin >> a >> b >> n;
ull modder = a - b;
if (modder != 0) {
ull out_res = 0;
bitset<bit_size> bin_rip(n);
ull first_mod_res = (modular_exponetiation(a, bin_rip, modder) +
modular_exponetiation(b, bin_rip, modder)) %
modder;
if (first_mod_res == 0)
out_res = modder;
else
out_res = euclid_gcd(modder, first_mod_res);
cout << out_res % 1000000007 << std::endl;
} else {
// mod by 0 is not defined using the problem defined result.
// GCD(0,a) == a;
ull modder = 1000000007;
bitset<bit_size> bin_rip(n);
ull res = (modular_exponetiation(a, bin_rip, modder) +
modular_exponetiation(b, bin_rip, modder)) %
modder;
cout << res << std::endl;
}
}
return 0;
}
请求
这不是作业,我也不需要精确的答案或代码更正。我明白所有这些,但不明白为什么它会在更大的值上失败?
任何方向或提示都会很有用。
【问题讨论】:
-
我不能在纸上做这样的数学。输入是疯狂的关于 1e12
-
我建议使用符号数学,即代数简化(在编码之前)。这可能会简化您的代码或使其更高效。但你可能想使用 GMPlib
-
看到有两个函数 euclid_gcd 和 modules_exponentiation。它们都是正确的,并且使用 c++ 中可用的最高容量 dtype。我猜这个问题与数学无关。边缘情况出现问题。
-
问题是算术问题,模算术和代数是数学的一部分。象征性地处理问题陈述应该会有所帮助
标签: c++ algorithm modular-arithmetic