如何在不到1秒的时间内计算2^x mod n=1
How to Calculate 2^x mod n = 1 in less than 1 second
我想写一个程序,计算2^x mod n = 1
,我们有n
是integer
,但我们应该计算x
。我写了代码,但我的代码在大n中工作太慢了。你能给我一个在1秒内解决这个问题的好方法吗
这是我的代码:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long int n,cntr=1,cheak;
cin >> n;
while (1)
{
if (n % 2 == 0)
{
break;
}
cheak=pow(2, cntr);
if (cheak % n == 1)
break;
cntr++;
}
cout << cntr << endl;
}
对当前方法的一些建议修改: nbsp注意:下面是更好的方法
- 将您的
long long int
更改为unsigned long long int
。这会给你多一点 - 将
while (1)
更改为while (cntr < 64)
。unsigned long long
的大小可能只有64位。(它保证至少是64位,但不能大于64位。)然而,您需要检查循环是否成功 - 更改
cheak
以将2n计算为1ull << cntr
。确保包含ull
后缀,表示这是unsigned long long
<<
运算符将比特向左移位。将所有位向左移动1将使该数字的整数值加倍,假设没有位从该值的左侧"移位"。因此,1 << n
将计算2n。
后缀ull
表示整数常数是unsigned long long
。如果省略此后缀,1
将被视为整数,并且超过31的移位值将无法执行您想要的操作。
然而,以上所有内容都只是对当前方法的改进。为了更好地理解这种语言,了解这些提炼是值得的。然而,他们并不着眼于大局。
模乘可以让你找到(A*B)mod C作为((A mod C)*(B mod C))mod C。这对我们有什么帮助?
我们可以重写整个算法,只将N
和X
限制为机器整数的精度,而不是2N:
int main()
{
unsigned int modulus;
unsigned int raised = 2;
int power = 1;
std::cin >> modulus;
if (modulus % 2 == 1)
{
while (raised % modulus != 1)
{
raised = ((unsigned long long)raised * 2) % modulus;
power++;
}
std::cout << power << std::endl;
} else
{
std::cout << "modulus must be odd" << std::endl;
}
}
上面对unsigned long long
的强制转换允许modulus
大到232-1,假设unsigned int
是32位,而没有计算溢出。
有了这种方法,即使输入量很大,我也能很快找到答案。例如,111111111
返回667332
。我使用任意精度计算器bc
验证了2677332mod11111==1。
速度很快。在我的电脑上,它在不到0.07秒内计算出了222323860mod4294967293==1。
Epilog:这突出了编程中的一个重要原则:实际上,这是一个数学问题,而不是编程问题。要找到一个有效的解决方案,需要比了解C++更多地了解问题领域。一旦我们确定了正确的数学方法,实际的C++代码就微不足道了。
它经常是这样的,无论是数学还是其他算法方面。而且,当你了解到离散数学是我们许多图和集合算法的来源时,你不应该感到惊讶。编程语言本身只是全局的一小部分。
对于1和ceil(sqrt(n))
之间的每个k
,计算2^k mod n
和2^(k ceil(sqrt(n))) mod n
。然后计算每个CCD_ 31的模逆。将所有inverse(2^k)
s排序为数组foo
,将2^(k ceil(sqrt(n))
s排序为阵列bar
。在这两个数组之间将至少有一个共同的值;找到它。说inverse(2^a) = 2^(b ceil(sqrt(n)))
。然后CCD_ 37。
你的教授的幽默感怎么样?
#include <iostream>
int main() { std::cout << 0 << 'n'; }
始终按说明打印问题的正确答案。
pow
在计算中相当昂贵,但如果将2作为其第一个参数,则可以更好地向左移动,因为向左移动等于乘以2:
cheak = (1 << cntr);
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 递归函数计算序列中的平方和(并输出过程)
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的字符计数代码计算错误.为什么
- 在计算中使用二的幂有多有利可图
- 如何计算文件中的"columns"数?
- 计算排序向量的向量中唯一值的计数
- 如何使用 std::累积在 C++ 中计算总和立方体
- 使用Qt C++计算类似Git的SHA1哈希
- OpenCV C++.快速计算混淆矩阵
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- C++如何计算用户输入的数字中的偶数位数
- 使用加法链接计算 (a^x)mod n.C++算法
- 当n变大时,在计算阶乘(N)mod m上遇到困难
- 如何在不到1秒的时间内计算2^x mod n=1
- 用mod和pow计算大数字
- 正在计算 (a^b)%MOD
- 计算 n,其中 a^n mod m = 1
- 用mpz_powm计算功率mod
- 利用模乘逆的概念计算nCr % MOD