快速计算 a^(b!模组(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
阶乘结果非常大,如果不使用 bigint,就不适合您的小 int 变量。但是您可以将计算稍微更改为:
10^(3!) mod c
= 10^(1*2*3) mod c
= (((10^1 mod c)^2 mod c)^3 mod c)
因此,这个想法不是通过将循环的迭代器相乘i
而不是在a^...
子结果上使用modpow
来计算阶乘。这样,所有子结果仍然适合您的变量。
这里有一个小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
模算术取自这里:
- 模块化算法和NTT(有限域DFT)优化
我使用了缓慢的非优化的,因此它可以在任何平台上编译和运行......
检查这个答案!
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); }
相关文章:
- 犰狳C++:带有模量计算的线性组合
- 我可以为unordered_map分配特定的模组值吗?
- 如何获得西格玛 NcR 模组1000000007
- 使用结构数组计算文本文件中单词的出现次数C++
- 使用 2D 数组计算总计、最高价和最低价
- C++:类似的模组操作打印不同的值
- MPI从双数组计算差号
- 二维数组:计算行的总和和列的乘积
- 从字符数组计算平均数
- 快速计算 a^(b!模组(c)
- 练习:使用数组计算方差
- 二维数组计算公式
- 从导入的二维数组计算平均值
- 如何使用模运算符计算小数
- 从数组计算数据的c++问题
- 这个代码如何使用64位乘法和模除法计算字节的奇偶校验
- 模组的重载分辨率
- 模组功能不起作用为什么
- 通过二维数组计算文件中的特定记录
- Python模拟显示慢性能,如何加快数组计算速度