簡體   English   中英

快速計算a ^(b!)mod(c)的方法

[英]fast way to calculate a^(b!)mod(c)

到目前為止,這是我嘗試過的。 我不知道這段代碼有什么問題,但是在大多數情況下,它給出了錯誤的答案:x,y,n> 10 ^ 5。

#include <stdio.h>
long long factorial(long long N)
{
  long long product = 1;
  for ( long long j=1;j<=N;j++)
    product *= j;
  return product;
}
long long power(long long x, unsigned long long y, long long p) 
{ 
    long long res = 1;      // Initialize result 

    x = x % p;  // Update x if it is more than or  
                // equal to p 

    while (y > 0) 
    { 
        // If y is odd, multiply x with result 
        if (y & 1) 
            res = (res*x) % p; 

        // y must be even now 
        y = y>>1; // y = y/2 
        x = (x*x) % p;   
    } 
    return res; 
} 
int main()  
{  
   long long A,B,C,test;
   scanf("%lld",&test);
   for (long long i = 0;i<test;i++)
   {
       scanf("%lld %lld %lld",&A,&B,&C);
        long long fa = factorial(B);
        long long res = power(A,fa,C);
        printf("%lld \n",res);
   }
   return 0;  
}

任何幫助或演練將不勝感激。

除了充分利用諸如Nico Schertler之類的數論知識外,在他的評論中還建議您也可以使用幼稚的方法在小整數上進行此操作。

您的問題是您的子結果不適合您的變量:

a^(b!) mod c < c
b! > c

階乘結果的確非常大,如果不使用bigints,它將不適合您的int小變量。 但是您可以對此稍作更改:

  10^(3!) mod c
= 10^(1*2*3) mod c
= (((10^1 mod c)^2 mod c)^3 mod c)

這樣的想法是不是乘以計算階乘i的循環使用迭代器modpowa^...子的結果。 這樣,所有子結果仍然適合您的變量。

這里是一個小的C ++代碼:

//---------------------------------------------------------------------------
typedef unsigned __int32 DWORD;
//---------------------------------------------------------------------------
DWORD mod(DWORD a,DWORD p)
    {
    DWORD bb;
    for (bb=p;(DWORD(a)>DWORD(bb))&&(!DWORD(bb&0x80000000));bb<<=1);
    for (;;)
        {
        if (DWORD(a)>=DWORD(bb)) a-=bb;
        if (bb==p) break;
        bb>>=1;
        }
    return a;
    }
//---------------------------------------------------------------------------
DWORD modadd(DWORD a,DWORD b,DWORD p)
    {
    DWORD d,cy;
    a=mod(a,p);
    b=mod(b,p);
    d=a+b;
    cy=((a>>1)+(b>>1)+(((a&1)+(b&1))>>1))&0x80000000;
    if (cy) d-=p;
    if (DWORD(d)>=DWORD(p)) d-=p;
    return d;
    }

//---------------------------------------------------------------------------
DWORD modsub(DWORD a,DWORD b,DWORD p)
    {
    DWORD d;
    a=mod(a,p);
    b=mod(b,p);
    d=a-b; if (DWORD(a)<DWORD(b)) d+=p;
    if (DWORD(d)>=DWORD(p)) d-=p;
    return d;
    }
//---------------------------------------------------------------------------
DWORD modmul(DWORD a,DWORD b,DWORD p)
    {
    int i;
    DWORD d;
    a=mod(a,p);
    for (d=0,i=0;i<32;i++)
        {
        if (DWORD(a&1))    d=modadd(d,b,p);
        a>>=1;
        b=modadd(b,b,p);
        }
    return d;
    }
//---------------------------------------------------------------------------
DWORD modpow(DWORD a,DWORD b,DWORD p)
    {
    int i;
    DWORD d=1;
    mod(a,p);
    for (i=0;i<32;i++)
        {
        d=modmul(d,d,p);
        if (DWORD(b&0x80000000)) d=modmul(d,a,p);
        b<<=1;
        }
    return d;
    }
//---------------------------------------------------------------------------
DWORD modpowfact(DWORD a,DWORD b,DWORD c) // returns a^(b!) mod c
    {
    DWORD i,y=mod(a,c);
    for (i=2;i<=b;i++)
     y=modpow(y,i,c);
    return y;
    }
//---------------------------------------------------------------------------

上面的代碼在我的設置中返回了這些代碼:

10^(0!) mod 1031 = 10
10^(1!) mod 1031 = 10
10^(2!) mod 1031 = 100
10^(3!) mod 1031 = 961
10^(4!) mod 1031 = 72
10^(5!) mod 1031 = 754

模塊化算法是從這里獲取的:

我使用了緩慢的非優化版本,因此可以在任何平台上編譯和運行...

檢查這個答案!

https://stackoverflow.com/a/26282858/7480909

我用這個功能解決這個問題

UVA 374-大模組

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=310

 // a^b % T // with Exponentiation by squaring (http://en.wikipedia.org/wiki/Exponentiation_by_squaring#Basic_method) // if a very large use // R=(unsigned long long)(R*a)%T; int restOfPot(long long a,int b,int T) { a%=T; long long R=1; while(b) { if(b&1) R=(R*a)%T; a=(a*a)%T; b>>=1; } return int(R); } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM