简体   繁体   English

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

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

Here is what I've tried so far. 到目前为止,这是我尝试过的。 I don't know what is wrong with this code, but it's giving the wrong answer for large cases: x,y,n > 10^5. 我不知道这段代码有什么问题,但是在大多数情况下,它给出了错误的答案: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;  
}

Any help or walkthrough will be appreciated. 任何帮助或演练将不胜感激。

well apart exploiting some knowledge from number theory like Nico Schertler suggests in his comment you can do this on small ints with naive approach too. 除了充分利用诸如Nico Schertler之类的数论知识外,在他的评论中还建议您也可以使用幼稚的方法在小整数上进行此操作。

Your problem is that your sub result is not fitting into your variables: 您的问题是您的子结果不适合您的变量:

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

The factorial result is really huge and will not fit into your small int variables without the use of bigints. 阶乘结果的确非常大,如果不使用bigints,它将不适合您的int小变量。 But you can change the computation slightly to this: 但是您可以对此稍作更改:

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

So the idea is instead of computing the factorial by multiplying i iterator of a loop use modpow on the a^... sub result. 这样的想法是不是乘以计算阶乘i的循环使用迭代器modpowa^...子的结果。 This way all the sub results still fits into your variables. 这样,所有子结果仍然适合您的变量。

Here a small C++ code for this: 这里是一个小的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;
    }
//---------------------------------------------------------------------------

the code above returns these on my setup: 上面的代码在我的设置中返回了这些代码:

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

the modular arithmetic was taken from here: 模块化算法是从这里获取的:

I used the slow non optimized ones so it can be compiled and run on any platform ... 我使用了缓慢的非优化版本,因此可以在任何平台上编译和运行...

check this answer! 检查这个答案!

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

I use this function to solve this problem 我用这个功能解决这个问题

UVA 374 - Big Mod UVA 374-大模组

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=310 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