我不知道为什么它大量使用不好,因为我已经最大限度地使用了unsigned long long
。请帮我。或者,如果此代码完全混乱,请建议更好,更有效的算法。这是一项功课,我们只允许使用#include <stdio.h>
和#include <stdlib.h>
。我希望你能帮助我。
unsigned long long modularexp(unsigned long long a,unsigned long long b,unsigned long long mod)
{
//a^b % mod
unsigned long long product,pseq;
product=1;
pseq=a%mod;
while(b>0)
{
if(b&1)
product=(product*pseq)%mod;
pseq=(pseq*pseq)%mod;
b>>=1;
}
return product;
}
答案 0 :(得分:4)
您的代码本身很好,但只有当模数小于2 ^ 32时才能可靠地工作。在您的情况下,模数超过2 ^ 32和以下:
a * b < ulong.max
不一定正确,即使a < mod
和b < mod
。
您可以通过向所有乘法添加溢出检查来解决此问题。如果乘法a * b
溢出,请细分a = a1 + a2
并计算a1 * b + a2 * b
。
下面的代码通过引入模块化乘法的附加功能来实现这一目的。
#include <stdio.h>
typedef unsigned long long ulong;
#define ULONG_MAX ((ulong) -1)
ulong modmul(ulong a, ulong b, ulong mod)
{
if (a == 0) return 0;
if (ULONG_MAX / a > b) {
return (a * b) % mod;
} else {
ulong a1 = a / 2;
ulong a2 = a - a1;
return (modmul(a1, b, mod) + modmul(a2, b, mod)) % mod;
}
}
ulong modexp(ulong a, ulong b, ulong mod)
{
ulong product = 1;
a = a % mod;
while (b > 0) {
if (b & 1) {
product = modmul(product, a, mod);
}
a = modmul(a, a, mod);
b >>= 1;
}
return product;
}
int main()
{
ulong a = modexp(1727, 62483, 7491569251LL);
ulong expect = 5500747491LL;
printf("%llu\n%llu\n", a, expect);
return 0;
}
答案 1 :(得分:0)
这是一个测试程序,显示溢出发生的位置:
#include <stdio.h>
#include <stdlib.h>
static
unsigned long long modularexp(unsigned long long a,
unsigned long long b,
unsigned long long mod)
{
unsigned long long product, pseq;
product = 1;
pseq = a % mod;
while (b > 0) {
if (b & 1) {
if (pseq != 0 && product * pseq / pseq != product) {
printf("multiplication overflow at b=%llu:"
" product=%llu, pseq=%llu\n",
b, product, pseq);
}
product = (product * pseq) % mod;
}
if (pseq != 0 && pseq * pseq / pseq != pseq) {
printf("multiplication overflow at b=%llu:"
" pseq=%llu\n",
b, pseq);
}
pseq = (pseq * pseq) % mod;
b >>= 1;
}
return product;
}
int main(int argc, char *argv[]) {
unsigned long long a, b, mod, res;
if (argc > 3) {
a = strtoull(argv[1], NULL, 0);
b = strtoull(argv[2], NULL, 0);
mod = strtoull(argv[3], NULL, 0);
res = modularexp(a, b, mod);
printf("%llu ** %llu %% %llu = %llu\n", a, b, mod, res);
}
}
使用您的值运行它会产生以下结果:
~/dev/stackoverflow > ./t47 1727 62483 7491569251
multiplication overflow at b=3905: product=5150827583, pseq=5846688665
multiplication overflow at b=3905: pseq=5846688665
multiplication overflow at b=488: pseq=6744552923
multiplication overflow at b=244: pseq=4362729489
multiplication overflow at b=61: pseq=6056813204
multiplication overflow at b=30: pseq=6747710262
multiplication overflow at b=15: pseq=5762416609
multiplication overflow at b=7: pseq=5992947929
multiplication overflow at b=3: pseq=6028562833
multiplication overflow at b=1: product=7015761607, pseq=7047166445
multiplication overflow at b=1: pseq=7047166445
1727 ** 62483 % 7491569251 = 4674220559
您必须使用M Oehm
提供的功能保护计算。