Cha*_*han 6 c c++ algorithm optimization numbers
因为,我需要计算,而且它必须非常快!
我目前的做法是:1 <= N <= 10000000002N mod 1000000007
ull power_of_2_mod(ull n) {
ull result = 1;
if (n <= 63) {
result <<= n;
result = result % 1000000007;
}
else {
ull one = 1;
one <<= 63;
while (n > 63) {
result = ((result % 1000000007) * (one % 1000000007)) % 1000000007;
n -= 63;
}
for (int i = 1; i <= n; ++i) {
result = (result * 2) % 1000000007;
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
但它似乎不够快.任何的想法?
这会更快(C中的代码):
typedef unsigned long long uint64;
uint64 PowMod(uint64 x, uint64 e, uint64 mod)
{
uint64 res;
if (e == 0)
{
res = 1;
}
else if (e == 1)
{
res = x;
}
else
{
res = PowMod(x, e / 2, mod);
res = res * res % mod;
if (e % 2)
res = res * x % mod;
}
return res;
}
Run Code Online (Sandbox Code Playgroud)
你可以在O(log n).
例如,对于 n = 1234 = 10011010010(以 2 为底),我们有 n = 2 + 16 + 64 + 128 + 1024,因此 2^n = 2^2 * 2^16 * 2^64 * 2^128 * 2 ^ 1024。
请注意,2^1024 = (2^512)^2,因此,如果您知道 2^512,则可以通过几次操作来计算 2^1024。
解决方案是这样的(伪代码):
const ulong MODULO = 1000000007;
ulong mul(ulong a, ulong b) {
return (a * b) % MODULO;
}
ulong add(ulong a, ulong b) {
return (a + b) % MODULO;
}
int[] decompose(ulong number) {
//for 1234 it should return [1, 4, 6, 7, 10]
}
//for x it returns 2^(2^x) mod MODULO
// (e.g. for x = 10 it returns 2^1024 mod MODULO)
ulong power_of_power_of_2_mod(int power) {
ulong result = 1;
for (int i = 0; i < power; i++) {
result = mul(result, result);
}
return result;
}
//for x it returns 2^x mod MODULO
ulong power_of_2_mod(int power) {
ulong result = 1;
foreach (int metapower in decompose(power)) {
result = mul(result, power_of_power_of_2_mod(metapower));
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
请注意,O(log n)实际上,O(1)对于ulong参数(如 log n < 63);并且此代码与任何uintMODULO (MODULO < 2^32)兼容,与MODULO 是否为素数无关。
小智 5
此方法不使用具有O(log(n))复杂度的递归.看一下这个.
#define ull unsigned long long
#define MODULO 1000000007
ull PowMod(ull n)
{
ull ret = 1;
ull a = 2;
while (n > 0) {
if (n & 1) ret = ret * a % MODULO;
a = a * a % MODULO;
n >>= 1;
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
这是来自维基百科的伪(参见从右到左的二进制方法部分)
function modular_pow(base, exponent, modulus)
Assert :: (modulus - 1) * (base mod modulus) does not overflow base
result := 1
base := base mod modulus
while exponent > 0
if (exponent mod 2 == 1):
result := (result * base) mod modulus
exponent := exponent >> 1
base := (base * base) mod modulus
return result
Run Code Online (Sandbox Code Playgroud)