如何在C ++ 14中确定4 ^(4 ^(10 ^ 9))%9 ^ 9的值?

时间:2017-06-09 20:03:12

标签: c++ algorithm c++14 mod bigmod

我已成功尝试使用9 ^(10 ^ 9)等数字的大模型算法。但是当权力太大而无法使用时,如何得到最终答案?

#include <iostream>
#include <cmath>
#define ULL unsigned long long
using namespace std;

ULL mod(ULL b, ULL p,ULL m)
{
    ULL md=1,c;
    while(p!=0)
{
    if (p % 2 == 0)
    {
        md*=(b%m)*(b%m);
        p=p/2;
    }
    else 
    {
        md*=(b % m);
        p--;
    }
}
    return md;
}

int main()
{
ULL b=4, p, m=pow(9,9), num,res;
cin >> p;
num= mod(b,p,m);
res=pow(num,4);
cout << res;
}

1 个答案:

答案 0 :(得分:1)

考虑计算(4 ^(p))%(9 ^ 9)的一般情况,其中p是大数(在这种情况下p = 4 ^(10 ^ 9))。考虑4模9 ^ 9的幂次序:(4 ^ 0)%(9 ^ 9)== 1,(4 ^ 1)%(9 ^ 9)== 4,(4 ^ 2)%(9 ^ 9)== 16,最终在t(t未知)循环之后,序列将循环回到(4 ^ t)%(9 ^ 9)== 1,之后它重复。 (注意数字必须是“互质”,否则经过一定数量的循环后,结果变为零并保持为零。)因此计算可以使用p%t而不是p:

(4^(p))%(9^9) == (4^(p%t))%(9^9)

这似乎很大,但是t将是&lt; = 9 ^ 9,并且9 ^ 9&lt; 2 ^ 29,和4 * 2 ^ 29 = 2 ^ 31,所以64位整数(平方加速取幂所需)将足以解决这个问题。所以现在的问题是解决问题。您可以通过以|开头来确定t m = 1 | t = 0 |然后用|循环m =(m * 4)%(9 ^ 9)| t + = 1 |直到m == 1再次。

例如,假设您正在寻找:

(4^(p))%9 == (4^(p%t))%9

对于这个更简单的例子:

(4^0)%9 == 1      ;m == 1, t == 0
(4^1)%9 == 4      ;m == 4, t == 1
(4^2)%9 == 7      ;m == 7, t == 2
(4^3)%9 == 1      ;m == 1, t == 3   (end of loop)

所以t == 3(对于这个更简单的情况):

(4^(p))%9 == (4^(p%3))%9

正如DAle评论的那样,还有与totient相关的欧拉定理:

https://en.wikipedia.org/wiki/Euler%27s_totient_function#Euler.27s_theorem

如果a和n是互质的,那么

(a^(ϕ(n)))%n = 1, where ϕ(n) is the totient function.

维基文章还包含了一个完整函数的公式。

https://en.wikipedia.org/wiki/Euler%27s_totient_function#Euler.27s_product_formula

你可以使用t =φ(9 ^ 9)。这不会是满足(4 ^(t))%(9 ^ 9)= 1的t的最小值,但它就足够了。

问题发布已经过去了两天,所以继续

t =φ(9 ^ 9)=φ(3 ^ 18)=(3 ^ 18)(1-1 / 3)= 2(3 ^ 17)= 258280326

使用循环方法找到一个较小的值,t = 3 ^ 17 = 129140163.然后将其用于内部幂模

p%t =((4 ^(10 ^ 9))%129140163)= 19457986

然后继续外功率模的过程

(4 ^(4 ^(10 ^ 9)))%(9%9)=(4 ^ 19457986)%(9 ^ 9)= 335228719

示例代码:

#include <stdio.h>

typedef unsigned long long uint64_t;

/* count number of cycles t such that */
/* (v^t)%m = 1 */
uint64_t cntcyc(uint64_t v, uint64_t m)
{
uint64_t t = 0;
uint64_t i = 1;
    do {
        i = (i * v) % m;
        t++;
    } while (i != 1);
    return t;
}

/* v to power p modulo m */
uint64_t powmod(uint64_t v, uint64_t p, uint64_t m)
{
uint64_t s = v;                         /* repeated square */
uint64_t r = 1;                             /* result */
    while(p){
        if(p&1)
            r = (r*s)%m;
        s = (s*s)%m;
        p >>= 1;
    }
    return r;
}

int main()
{
uint64_t r;
    r = cntcyc(4ull, 387420489ull);      /* 4, 9^9 */
    printf("%llu\n", r);                 /*   129140163 */
    r = powmod(4ull, 1000000000ull, r);  /* (4^(10^9))%r */
    printf("%llu\n", r);                 /*   19457986 */
    r = powmod(4ull, r, 387420489ull);   /* (4^r)%(9^9) */
    printf("%llu\n", r);                 /*   335228719 */
    r = 258280326ull;                    /* r = totient(9^9) */
    r = powmod(4ull, 1000000000ull, r);  /* (4^(10^9))%r */
    printf("%llu\n", r);                 /*   19457986 */
    r = powmod(4ull, r, 387420489ull);   /* (4^r)%(9^9) */
    printf("%llu\n", r);                 /*   335228719 */
    r = 258280326ull;                    /* r = totient(9^9) */
    r = powmod(4ull, 1000000000ull, r);  /* (4^(10^9))%r */
    /* show that r += 3^17 doesn't effect final result */
    r += 129140163ull;                   /* r += 3^17 */
    printf("%llu\n", r);                 /*   148598149 */
    r = powmod(4ull, r, 387420489ull);   /* (4^r)%(9^9) */
    printf("%llu\n", r);                 /*   335228719 */
    return 0;
}