Find (num * (pow(b, p) - 1) / den) % mod where p is very large(10 ^ 18)
Find (num * (pow(b, p) - 1) / den) % mod where p is very large(10 ^ 18)
我想找到 (num * (pow(b, p) - 1) / den) % mod。我知道二进制求幂。但我们不能直截了当地做到这一点。保证分子可以被分母整除。这意味着
[num * (pow(b, p) - 1)] % den == 0
对 mod 的约束:1 <= mod <= 10 ^ 9 并且 mod 可能是质数或合数
对 b 的约束:1 <= b <= 10
对 p 的约束:1 <= p <= (10^18)
对 num 的限制:1 <= num <= (10^9)
den 的约束:1 <= den <= (10^9)
这里的 pow(b, p) 表示 b 的幂 p(b ^ p)。保证分子可以被分母整除。我怎样才能用二进制求幂
您的表达式应该重写以简化它。首先让k=num/den,k根据你的问题整数。
所以你必须计算
(k×(b^p-1))mod m=( (k mod m) × ((b^p -1) mod m) ) mod米
= ( (k mod m) × ( (b^p mod m) -1 mod m ) mod m ) mod m
= ((k mod m) × ((b^p mod m) + m-1) mod m) mod m (1)
所以真正的问题是计算 b^p mod m
许多语言(python、java 等)在其标准库中已经有 mod 元求幂。查阅文档并使用它。否则,这里是 C 实现。
unsigned long long modexp(unsigned long long b, unsigned long long e, unsigned long long m) {
if (m==1) return 0;
unsigned long long res=1;
unsigned long long bb = b % m;
while (e) {
if (e & 1)
res = (res*b) % m;
e >>= 1;
bb = (bb*bb) % m;
}
return res;
}
实施使用 long long
来满足您的限制。它依赖于二进制取幂的经典技巧。 b^l 的所有值,其中 l 是 2 的幂 (l=2^t) 被计算并存储在 var bb 中,如果 e 的相应 tth 位被设置, b^l 的这个值集成在结果中。位测试通过检查 e 的连续奇偶校验来完成,同时在每一步向右移动 e。
最后,(a×b)mod m=((a mod m)×(b mod m))mod m 是用于避免对非常大的数字进行计算。我们总是有 res
那么您只需应用(1)即可得到最终结果。
根据评论中给出的精度进行编辑
要计算 n=(3^p-1)/2 mod m,可以注意到
(3^p-1)/2 = x*m + n(因为3^p-1是偶数,x是整数,0≤n
3^p-1=x*2*m+2n (0≤2n<2m)
所以 2n=(3^p-1) mod 2m
我们可以只应用前面的方法,modulo 为 2*m,并将结果(这将是偶数)除以 2。
我想找到 (num * (pow(b, p) - 1) / den) % mod。我知道二进制求幂。但我们不能直截了当地做到这一点。保证分子可以被分母整除。这意味着
[num * (pow(b, p) - 1)] % den == 0
对 mod 的约束:1 <= mod <= 10 ^ 9 并且 mod 可能是质数或合数
对 b 的约束:1 <= b <= 10
对 p 的约束:1 <= p <= (10^18)
对 num 的限制:1 <= num <= (10^9)
den 的约束:1 <= den <= (10^9)
这里的 pow(b, p) 表示 b 的幂 p(b ^ p)。保证分子可以被分母整除。我怎样才能用二进制求幂
您的表达式应该重写以简化它。首先让k=num/den,k根据你的问题整数。
所以你必须计算
(k×(b^p-1))mod m=( (k mod m) × ((b^p -1) mod m) ) mod米
= ( (k mod m) × ( (b^p mod m) -1 mod m ) mod m ) mod m
= ((k mod m) × ((b^p mod m) + m-1) mod m) mod m (1)
所以真正的问题是计算 b^p mod m
许多语言(python、java 等)在其标准库中已经有 mod 元求幂。查阅文档并使用它。否则,这里是 C 实现。
unsigned long long modexp(unsigned long long b, unsigned long long e, unsigned long long m) {
if (m==1) return 0;
unsigned long long res=1;
unsigned long long bb = b % m;
while (e) {
if (e & 1)
res = (res*b) % m;
e >>= 1;
bb = (bb*bb) % m;
}
return res;
}
实施使用 long long
来满足您的限制。它依赖于二进制取幂的经典技巧。 b^l 的所有值,其中 l 是 2 的幂 (l=2^t) 被计算并存储在 var bb 中,如果 e 的相应 tth 位被设置, b^l 的这个值集成在结果中。位测试通过检查 e 的连续奇偶校验来完成,同时在每一步向右移动 e。
最后,(a×b)mod m=((a mod m)×(b mod m))mod m 是用于避免对非常大的数字进行计算。我们总是有 res 那么您只需应用(1)即可得到最终结果。 根据评论中给出的精度进行编辑 我们可以只应用前面的方法,modulo 为 2*m,并将结果(这将是偶数)除以 2。
要计算 n=(3^p-1)/2 mod m,可以注意到
(3^p-1)/2 = x*m + n(因为3^p-1是偶数,x是整数,0≤n
所以 2n=(3^p-1) mod 2m