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.
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. 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. This way all the sub results still fits into your variables.
Here a small C++ code for this:
//---------------------------------------------------------------------------
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 ...