如何用1计算(x y )mod z &lt; = x,y&lt; = 10 1000 并且z任何正整数1 <= z <1。 2 31
到目前为止,我所做的是: 将x和y扫描为一个字符串,得到模数,然后计算(x y )mod z。
我知道这是错误的,因为(x y )mod z不等于((x mod z)(y mod z))mod z。那怎么解决这个问题呢?
编辑:抱歉,我在创建问题时将x和y的底部约束设置得如此之高。我只想关注大整数问题,而不是模幂运算:)。
#define MOD z
long long power (long long k, long long n) {
if (n == 1) return k;
else {
long long p = power (k, n/2);
if (n % 2 == 0) return (p * p) % MOD;
else return (((p * p) % MOD) * k) % MOD;
}
}
long long convert (char *n) {
long long number = 0;
int ln = strlen (n);
for (int x = 0; x < ln; x++) {
number = number * 10;
number = (number + (n[x] - '0')) % MOD;
}
return number % MOD;
}
int main () {
char s_x[1111], s_y[1111];
scanf ("%s %s", s_x, s_y);
long long x, y, r;
x = convert (s_x);
y = convert (s_y);
r = power (x, y);
printf ("%lld\n", r);
}
答案 0 :(得分:2)
由于模块化指数的使用非常多,因此有适用于它的库。以下是使用GMP读取a,b和c并输出 b mod c的示例。
#include <stdio.h>
#include <gmp.h>
int main(void)
{
mpz_t a, b, c, d;
mpz_inits (a, b, c, d, NULL);
printf ("a: ");
mpz_inp_str (a, stdin, 10);
printf ("b: ");
mpz_inp_str (b, stdin, 10);
printf ("c: ");
mpz_inp_str (c, stdin, 10);
mpz_powm (d, a, b, c); // compute d = a ^ b mod c
gmp_printf ("a ^ b mod c = %Zd\n", d);
return 0;
}
使用-lgmp
编译。
顺便说一下, b ≡a bmodΦ(c)(mod c),其中Φ是Euler's totient function
答案 1 :(得分:1)
首先,我假设z
相当小(如,适合长)。还要注意
(x ^ y) % z = ((x % z) ^ y) % z
因此,按照您的方式转换x
是可以的,唯一的问题是y
。方便的是,你只用y
做两件事 - 你把它除以2,然后在除以2之后检查余数。如果将y
表示为数组,那么这两件事都是微不足道的。首先,为了简单起见,反转y
,以便最低有效数字首先出现,并且还存储数字,而不是数组中的数字字符(如存储5,不是&#39; 5&#39;)。您可能还考虑在每个元素中存储多于一个数字,但这只会通过常量来改进它。
现在检查余数,只检查数组的第一个元素是否可被2整除(即使其最低有效数字为偶数,该数字也是如此)。除以二,做一些事情:
for (int i = 0; i < y_len; ++ i) {
if (i && y[i] % 2) y[i - 1] += 5;
y[i] /= 2;
}
if (y_len && y[y_len - 1] == 0) -- y_len;
将此插入您的power
例程,它会正常工作。请注意,power
方法在y
中是对数的,因此y
可以达到10^1000
这一事实并不会使其无法缓慢发挥作用。
答案 2 :(得分:0)
我猜您正在尝试构建Diffie-Hellman Key Exchange算法。尝试导入OpenSSL库,然后使用它的BN_mod_exp()
函数。
BN_mod_exp()计算a到p次幂模m(r = a ^ p%m)。此函数比BN_exp()使用更少的时间和空间。
来源:https://www.openssl.org/docs/manmaster/crypto/BN_add.html
答案 3 :(得分:0)
感谢@ v7d8dpo4对Euler的Totient功能的解释。 我编辑了以下代码:
#define MOD z
long long power (long long k, long long n) {
if (n == 1) return k;
else {
long long p = power (k, n/2);
if (n % 2 == 0) return (p * p) % MOD;
else return (((p * p) % MOD) * k) % MOD;
}
}
long long convert (char *n, int mod) {
long long number = 0;
int ln = strlen (n);
for (int x = 0; x < ln; x++) {
number = number * 10;
number = (number + (n[x] - '0')) % mod;
}
return number % mod;
}
int main () {
char s_x[1111], s_y[1111];
scanf ("%s %s", s_x, s_y);
long long x, y, r;
x = convert (s_x, MOD);
y = convert (s_y, totient (MOD)); // totient (x) is Euler's Totient Function of x
r = power (x, y);
printf ("%lld\n", r);
}