模数乘法逆

时间:2017-08-06 19:10:54

标签: c number-theory

我计算((A ^ B)/ C)%M,但是当A,B,C,M数量很大时,我的代码不起作用。当A,B,C,D小int时,此代码给出正确答案。

这里有什么问题?

此处C和M是共同主要

示例输入    2 3 4 5 示例输出    2

这些输入的代码失败    969109092 60139073 122541116 75884463

C程序

#include <stdio.h>

int d,x,y;

模块指数(A ^ B)%M

int power(int A, int B, int M)
{
    long long int result=1;
    while(B>0)
    {
        if(B % 2 ==1)
        {
            result=(result * A)%M;
        }
        A=(A*A)%M;
        B=B/2;
    }
    return result;
}

模块乘法逆

void extendedEuclid(int A, int B)
{
    if(B == 0)
    {
        d = A;
        x = 1;
        y = 0;
    }
    else
    {
        extendedEuclid(B,A%B);
        int temp = x;
        x = y;
        y = temp - (A/B)*y;
    }
}

int modInv(int A, int M)
{
    extendedEuclid(A,M);
    return (x%M+M)%M;
}

主要()

int main()
{
    int A,B,C,M;
    scanf("%d %d %d %d",&A,&B,&C,&M);
    int inv = modInv(C,M)%M;
    printf("%d\n",inv);
    long long int p = (power(A,B,M))%M;
    printf("%d\n",p);
    long long int ans = (p * inv)%M;
    //printf("%d",((modInv(C,M)*(power(A,B,M))))%M);
    printf("%lld",ans);
    return 0;
}

3 个答案:

答案 0 :(得分:1)

代码至少存在以下问题:

{p} int溢出A*A。代码需要使用更宽的数学计算产品A*A。这就是为什么代码使用较小的值,但不是很大。

// A=(A*A)%M;
A = ((long long)A*A) % M;
// or 
A = (1LL*A*A) % M;

错误的打印说明符。这意味着编译器警告未完全启用。节省时间,全部启用。

long long int p = (power(A,B,M))%M;
// printf("%d\n",p);
printf("%lld\n",p);

代码不对,负值。而不是修补int个洞,使用 unsigned 类型。

unsigned power(unsigned A, unsigned B, unsigned M) {
  unsigned long long result = 1;
  ...

power(A,0,1)中的角落案例失败。 resultM==1应为0。

// long long int result=1;
long long int result=1%M;

答案 1 :(得分:1)

测试版本中包含修复内容:

#include <stdio.h>

int d,x,y;

int power(int A, int B, int M)
{
    long long int result=1;
    long long int S = A;            /* fix */
    while(B>0)
    {
        if(B % 2 ==1)
        {
            result=(result * S)%M;  /* fix */
        }
        S=(S*S)%M;                  /* fix */
        B=B/2;
    }
    return (int)result;
}

void extendedEuclid(int A, int B)
{
int temp;                           /* C */
    if(B == 0)
    {
        d = A;
        x = 1;
        y = 0;
    }
    else
    {
        extendedEuclid(B,A%B);
        temp = x;
        x = y;
        y = temp - (A/B)*y;
    }
}

int modInv(int A, int M)
{
    extendedEuclid(A,M);
/*  x = x%M;                        ** not needed */
    if (x < 0)                      /* fix */
        x += M;                     /* fix */
    return (x);                     /* fix */
}

int main()
{
    int A,B,C,M;                    /* C */
    int inv, p, ans;                /* C */
    A = 969109092;                  /* 2^2 × 3^2 ×7 × 1249 × 3079 */
    B =  60139073;                  /* 60139073 */
    C = 122541116;                  /* 2^2 × 1621 × 18899 */
    M =  75884463;                  /* 3^2 × 8431607 */

    inv = modInv(C,M)%M;            /* 15543920 */
    printf("%d\n",inv);
    p = power(A,B,M)%M;             /*  6704397 */
    printf("%d\n",p);
    ans = (unsigned)(((unsigned long long)p * inv)%M);  /* fix 22271562 */
    printf("%d\n",ans);
    return 0;
}

答案 2 :(得分:0)

int的值可能不够大,请尝试使用long或double。

小心,因为power返回int不长long int