【问题标题】:How can I determine the value of 4^(4^(10^9))%9^9 in C++14?如何确定 C++14 中 4^(4^(10^9))%9^9 的值?
【发布时间】:2017-11-11 22:47:22
【问题描述】:

我已经用 9^(10^9) 这样的数字成功地尝试了 big mod 算法。但是当功率也太大而无法使用时,如何获得最终答案?

#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;
}

【问题讨论】:

  • 这里没有x^4,注意模幂:指数不取模与整个数字相同
  • 您是否在问如果p 不适合unsigned long long 应该怎么办?或者您需要准确计算主题中的那个数字?
  • 是的,我在问如果 p 不适合 unsigned long long @DAle 该怎么办
  • @SamnanRahee,使用长算法库,en.wikipedia.org/wiki/… 或者您可以自己实现它。顺便说一句,您的mod 函数并不完全正确。
  • 哪里出错了? :(@DAle

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


【解决方案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 将

例如,假设您正在寻找 t,这样:

(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.

wiki 文章还包括一个用于 totient 函数的公式。

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;
}

【讨论】:

  • 您给出的最后一个答案正是我正在寻找的@rcgldr 非常感谢。很抱歉给我带来的不便,我最近有点忙,无法登录 Stacksoverflow。
猜你喜欢
  • 2020-11-27
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-10
  • 2018-03-09
相关资源
最近更新 更多