我想计算:
你知道任何有效的方法,因为这个数字太大但a,b,c,...和m适合一个简单的32位int。
任何想法?
警告:这个问题与找到 b mod m不同。
另请注意, b c 与(a b ) c 不同。后者等于 bc 。指数是右关联的。
答案 0 :(得分:20)
a b c mod m = a b c mod n mod m,其中n =φ( m)Euler's totient function。
如果m是素数,那么n = m-1。
编辑:正如Nabb指出的那样,只有当a与m相互作用时才会成立。所以你必须先检查一下。
答案 1 :(得分:1)
因为对于任何关系a=x^y
,关系对于您使用的数字基础(基数2,基数6,基数16等)是不变的。
由于mod N操作相当于提取基数N中的最低有效位(LSD)
由于基数N中结果A的LSD只能受基数N中X的LSD影响,而不能影响较高位置的数字。 (例如34 * 56 = 30 * 50 + 30 * 6 + 50 * 4 + 4 * 5 = 10 *(3 + 50 + 3 * 6 + 5 * 4)+ 4 * 6)
因此,从LSD(A)=LSD(X^Y)
我们可以推断出
LSD(A)=LSD(LSD(X)^Y)
因此
A mod N = ((X mod N) ^ Y) mod N
和
(X ^ Y) mod N = ((X mod N) ^ Y) mod N)
因此,您可以在每个功率步骤之前执行mod,这会将结果保持在整数范围内。
这假定a不是负的,并且对于任何x ^ y,a ^ y< MAXINT
这个答案回答了错误的问题。 (亚历)
答案 2 :(得分:1)
Modular Exponentiation是解决这个问题的正确方法,这里有一点提示:
找到 b c d %m
你必须从计算开始
a%m,然后是 b %m,然后是 b c %m,然后是 b c d %m ...(你明白了)
要找到 b %m,您基本上需要两个想法:[设B =楼层(b / 2)]
因此,
如果b是偶数
a b %m =(a B %m) 2 %m
或者如果b是奇数
a b %m =((( B %m) 2 )*(a%m))%m
< / p>
因此,如果您知道 B 的值,则可以计算该值。
要找到 B ,请应用类似方法,将B除以1,直到达到1。
e.g。计算16 13 %11:
16 13 %11 =(16%11) 13 %11 = 5 13 %11
=(5 6 %11)*(5 6 %11)*(5%11)&lt; ----(I)
>
找到5 6 %11:
5 6 %11 =((5 3 %11)*(5 3 %11))%11&lt; -----( II)
找到5 3 %11:
5 3 %11 =((5 1 %11)*(5 1 %11)*(5%11))%11 <登记/>
=(((5 * 5)%11)* 5)%11 =((25%11)* 5)%11 =(3 * 5)%11 = 15%11 = 4
将该值插入(II)给出
5 6 %11 =(((4 * 4)%11)* 5)%11 =((16%11)* 5)%11 =(5 * 5)%11 = 25% 11 = 3
将该值插入(I)给出
5 13 %11 =((3%11)*(3%11)* 5)%11 =((9%11)* 5)%11 = 45%11 = 4 >
这样5 13 %11 = 4
有了这个你可以计算出任何形式 5 13 %11等等...
答案 3 :(得分:0)
查看A^X mod M
增加X
时的行为。它最终必须进入一个循环。假设周期的长度为P
,并在N
步之后开始。然后X >= N
隐含A^X = A^(X+P) = A^(X%P + (-N)%P + N) (mod M)
。因此,我们可以通过计算A^B^C
计算y=B^C, z = y < N ? y : y%P + (-N)%P + N, return A^z (mod m)
。
请注意,我们可以递归地将此策略应用于幂树,因为派生的等式具有指数&lt; M
或涉及较小指数塔的指数,且股息较小。
唯一的问题是,如果您能够有效地计算N
和P
给定A
和M
。请注意,高估N
很好。我们可以将N
设置为M
,事情就会成功。 P
有点困难。如果A
和M
是不同的素数,那么P=M-1
。如果A
包含所有M
的素数因子,那么我们会陷入0和P=1
。我会把它作为练习来解决这个问题,因为我不知道如何。
///Returns equivalent to list.reverse().aggregate(1, acc,item => item^acc) % M
func PowerTowerMod(Link<int> list, int M, int upperB = M)
requires M > 0, upperB >= M
var X = list.Item
if list.Next == null: return X
var P = GetPeriodSomehow(base: X, mod: M)
var e = PowerTowerMod(list.Next, P, M)
if e^X < upperB then return e^X //todo: rewrite e^X < upperB so it doesn't blowup for large x
return ModPow(X, M + (e-M) % P, M)
答案 4 :(得分:0)
Tacet的回答很好,但可以进行大量的简化。
x,mod m的幂是预周期的。如果x是m的相对素数,x的幂是周期性的,但即使没有这个假设,周期之前的部分也不长,最多是m的素数因式分解中的指数的最大值,最多为log_2 m 。周期的长度除以phi(m),实际上是lambda(m),其中lambda是Carmichael's function,最大乘法次序mod m。这可以显着小于phi(m)。 Lambda(m)可以从m的素因数分解快速计算,就像phi(m)一样。 Lambda(m)是在m的素因数分解中的所有素数p_i ^ e_i上的λ(p_i ^ e_i)的GCD,并且对于奇次幂,λ(p_i ^ e_i)= phi(p_i ^ e ^ i)。 lambda(2)= 1,lamnda(4)= 2,lambda(2 ^ n)= 2 ^(n-2),更大的幂为2。
将modPos(a,n)定义为{0,1,..,n-1}中a的同余类的代表。对于非负a,这只是%n。对于负数,由于某种原因,%n被定义为负数,因此modPos(a,n)是(a%n)+ n。
将modMin(a,n,min)定义为与mod n至少为min的最小正整数。对于正数,您可以将其计算为min + modPos(a-min,n)。
如果b ^ c ^ ...小于log_2 m(并且我们可以通过递归取对数来检查这个不等式是否成立),那么我们可以简单地计算一个^ b ^ c ^ ...否则,a ^ b ^ c ^ ... mod m = a ^ modMin(b ^ c ^ ...,lambda(m),[log_2 m]))mod m = a ^ modMin(b ^ c ^ ... mod lambda(m ),lambda(m),[log_2 m])。
例如,假设我们要计算2 ^ 3 ^ 4 ^ 5 mod 100.注意3 ^ 4 ^ 5只有489个数字,所以这可以通过其他方法来实现,但是它足够大了你不想直接计算它。但是,通过我在这里给出的方法,您可以手动计算2 ^ 3 ^ 4 ^ 5 mod 100.
从3 ^ 4 ^ 5&gt; log_2 100,
2^3^4^5 mod 100
= 2^modMin(3^4^5,lambda(100),6) mod 100
= 2^modMin(3^4^5 mod lambda(100), lambda(100),6) mod 100
= 2^modMin(3^4^5 mod 20, 20,6) mod 100.
让我们计算3 ^ 4 ^ 5 mod 20.由于4 ^ 5&gt; log_2 20,
3^4^5 mod 20
= 3^modMin(4^5,lambda(20),4) mod 20
= 3^modMin(4^5 mod lambda(20),lambda(20),4) mod 20
= 3^modMin(4^5 mod 4, 4, 4) mod 20
= 3^modMin(0,4,4) mod 20
= 3^4 mod 20
= 81 mod 20
= 1
我们可以将其插入以前的计算中:
2^3^4^5 mod 100
= 2^modMin(3^4^5 mod 20, 20,6) mod 100
= 2^modMin(1,20,6) mod 100
= 2^21 mod 100
= 2097152 mod 100
= 52.
注意2 ^(3 ^ 4 ^ 5 mod 20)mod 100 = 2 ^ 1 mod 100 = 2,这是不正确的。你不能减少到基数权力的预期部分。