我正在尝试解决问题,其中一部分需要我计算(2 ^ n)%1000000007,其中n <= 10 ^ 9。但是我的下面的代码给出了输出“0”,即使是像n = 99这样的输入。
除了有一个循环,每次都将输出多次输出2并且每次都找到模数时(不是我正在寻找,因为这对于大数字来说会非常慢)。
#include<stdio.h>
#include<math.h>
#include<iostream>
using namespace std;
int main()
{
unsigned long long gaps,total;
while(1)
{
cin>>gaps;
total=(unsigned long long)powf(2,gaps)%1000000007;
cout<<total<<endl;
}
}
答案 0 :(得分:2)
你需要一个“大数”库,不清楚你在哪个平台,但从这里开始: http://gmplib.org/
答案 1 :(得分:2)
这不是我要找的,因为这对于大数字来说会非常慢
使用bigint库的速度会比任何其他解决方案慢很多。
不要在每次通过循环时取模数:相反,只有在输出变得大于模数时才接受它,如下所示:
#include <iostream>
int main() {
int modulus = 1000000007;
int n = 88888888;
long res = 1;
for(long i=0; i < n; ++i) {
res *= 2;
if(res > modulus)
res %= modulus;
}
std::cout << res << std::endl;
}
这实际上很快:
$ time ./t
./t 1.19s user 0.00s system 99% cpu 1.197 total
我应该提一下,其工作原因是,如果 a 和 b 等效mod m (即 a %m = b%m ),则此等式包含 a 和 b 的多个 k (即上述等式暗示(a * k)%m =(b * k)%m )。
答案 2 :(得分:0)
Chris 提出了GMP,但是如果你需要这样做并且想要做C ++方式,而不是C方式,并且没有不必要的复杂性,你可能只想检查this out - 它在编译时产生很少的警告,但很简单,Just Works™。
答案 3 :(得分:0)
您可以将2^n
拆分为2^m
的块。你需要找到:`
2^m * 2^m * ... 2^(less than m)
m
应为31
,适用于32位CPU。那么你的回答是:
chunk1 % k * chunk2 * k ... where k=1000000007
你还是O(N)
。但是,你可以利用所有chunk % k
除了最后一个之外都是平等的事实,你可以做到O(1)
答案 4 :(得分:0)
我写了这个函数。它的效率很低,但是可以处理大量的数据。它使用我自己制定的算法,使用类似十进制的系统将大数字存储在数组中。
mpfr2.cpp
#include "mpfr2.h"
void mpfr2::mpfr::setNumber(std::string a) {
for (int i = a.length() - 1, j = 0; i >= 0; ++j, --i) {
_a[j] = a[i] - '0';
}
res_size = a.length();
}
int mpfr2::mpfr::multiply(mpfr& a, mpfr b)
{
mpfr ans = mpfr();
// One by one multiply n with individual digits of res[]
int i = 0;
for (i = 0; i < b.res_size; ++i)
{
for (int j = 0; j < a.res_size; ++j) {
ans._a[i + j] += b._a[i] * a._a[j];
}
}
for (i = 0; i < a.res_size + b.res_size; i++)
{
int tmp = ans._a[i] / 10;
ans._a[i] = ans._a[i] % 10;
ans._a[i + 1] = ans._a[i + 1] + tmp;
}
for (i = a.res_size + b.res_size; i >= 0; i--)
{
if (ans._a[i] > 0) break;
}
ans.res_size = i+1;
a = ans;
return a.res_size;
}
mpfr2::mpfr mpfr2::mpfr::pow(mpfr a, mpfr b) {
mpfr t = a;
std::string bStr = "";
for (int i = b.res_size - 1; i >= 0; --i) {
bStr += std::to_string(b._a[i]);
}
int i = 1;
while (!0) {
if (bStr == std::to_string(i)) break;
a.res_size = multiply(a, t);
// Debugging
std::cout << "\npow() iteration " << i << std::endl;
++i;
}
return a;
}
mpfr2.h
#pragma once
//#infdef MPFR2_H
//#define MPFR2_H
// C standard includes
#include <iostream>
#include <string>
#define MAX 0x7fffffff/32/4 // 2147483647
namespace mpfr2 {
class mpfr
{
public:
int _a[MAX];
int res_size;
void setNumber(std::string);
static int multiply(mpfr&, mpfr);
static mpfr pow(mpfr, mpfr);
};
}
//#endif
main.cpp
#include <iostream>
#include <fstream>
// Local headers
#include "mpfr2.h" // Defines local mpfr algorithm library
// Namespaces
namespace m = mpfr2; // Reduce the typing a bit later...
m::mpfr tetration(m::mpfr, int);
int main() {
// Hardcoded tests
int x = 7;
std::ofstream f("out.txt");
m::mpfr t;
for(int b=1; b<x;b++) {
std::cout << "2^^" << b << std::endl; // Hardcoded message
t.setNumber("2");
m::mpfr res = tetration(t, b);
for (int i = res.res_size - 1; i >= 0; i--) {
std::cout << res._a[i];
f << res._a[i];
}
f << std::endl << std::endl;
std::cout << std::endl << std::endl;
}
char c; std::cin.ignore(); std::cin >> c;
return 0;
}
m::mpfr tetration(m::mpfr a, int b)
{
m::mpfr tmp = a;
if (b <= 0) return m::mpfr();
for (; b > 1; b--) tmp = m::mpfr::pow(a, tmp);
return tmp;
}
我创建这个对象是为了四分法和最终的超手术。当数字真的很大时,可能要花很多时间才能计算出来,并且会占用大量内存。 #define MAX 0x7fffffff/32/4
是一个数字可以包含的小数位数。稍后我可能会提出另一种算法,将多个数组组合成一个数字。在我的系统上,最大数组长度为0x7fffffff aka 2147486347 aka 2 ^ 31-1 aka int32_max(通常是标准int大小),因此我不得不将int32_max设置为32,以使创建此数组成为可能。我还将其划分为4,以减少multiply()
函数中的内存使用。
-朱比曼