私は解が2 ^(n-1)である単純な結合問題を解く途中です。巨大な数値の効率的な指数化(私はGoogolsと話している)
唯一の問題は、1 < = N <ある= 2^31 -1(符号付き32ビット整数の最大値)
私はJavaのBigIntegerのクラスを使用して試みたが、タイムアウト番号2^10分の31用^ 4以上では、明らかにうまくいかない。
また、JavaまたはC++の組み込みクラスのみに限定されています。
私はスピードが必要であることを知っているので、私は文字列の算術演算を行うC++でクラスを作成することを選択しました。
私は乗算を行うと、私のプログラムは、紙の上に乗って効率を上げる方法(繰り返し文字列を追加するのではなく)と同様に乗算します。
しかし、それがあっても、2を31倍にすることはできません。それだけでは十分ではありません。
だから、これは私は、べき乗を解決することができることを意味し
(/整数の除算を表し、%はモジュラスを表す)私はこの問題にテキストを読み始めて、私は
2^n = 2^(n/2) * 2^(n/2) * 2^(n%2)
...の溶液に来ました乗数の対数。しかし、私には、このメソッドを自分のコードにどのように適用すればいいのでしょうか?どのようにして下限を選ぶのですか、最終的な乗算に必要なさまざまな数値を追跡する最も効率的な方法は何ですか?
誰かがこの問題の解決方法について知識を持っている場合は、詳細を教えてください(サンプルコードは高く評価されます)。すべてのあなたの助けをみんなに
UPDATE
ありがとう!明らかにこの問題は現実的な方法で解決されることを意図していますが、ceil(log2(n))回だけを実行するパワー関数を使ってjava.math.BigInteger
を上回る性能を達成しました。
誰もが私が作成したコードに興味がある場合は、ここではそれはあなたがまったくの乗算を行う必要はありません...
using namespace std;
bool m_greater_or_equal (string & a, string & b){ //is a greater than or equal to b?
if (a.length()!=b.length()){
return a.length()>b.length();
}
for (int i = 0;i<a.length();i++){
if (a[i]!=b[i]){
return a[i]>b[i];
}
}
return true;
}
string add (string& a, string& b){
if (!m_greater_or_equal(a,b)) return add(b,a);
string x = string(a.rbegin(),a.rend());
string y = string(b.rbegin(),b.rend());
string result = "";
for (int i = 0;i<x.length()-y.length()+1;i++){
y.push_back('0');
}
int carry = 0;
for (int i =0;i<x.length();i++){
char c = x[i]+y[i]+carry-'0'-'0';
carry = c/10;
c%=10;
result.push_back(c+'0');
}
if (carry==1) result.push_back('1');
return string(result.rbegin(),result.rend());
}
string multiply (string&a, string&b){
string row = b, tmp;
string result = "0";
for (int i = a.length()-1;i>=0;i--){
for (int j= 0;j<(a[i]-'0');j++){
tmp = add(result,row);
result = tmp;
}
row.push_back('0');
}
return result;
}
int counter = 0;
string m_pow (string&a, int exp){
counter++;
if(exp==1){
return a;
}
if (exp==0){
return "1";
}
string p = m_pow(a,exp/2);
string res;
if (exp%2==0){
res = "1"; //a^exp%2 is a^0 = 1
} else {
res = a; //a^exp%2 is a^1 = a
}
string x = multiply(p,p);
return multiply(x,res);
//return multiply(multiply(p,p),res); Doesn't work because multiply(p,p) is not const
}
int main(){
string x ="2";
cout<<m_pow(x,5000)<<endl<<endl;
cout<<counter<<endl;
return 0;
}
C++にはビルトインビッグクラスはありません。まだ普及しているライブラリを検討したいのですか?または質問からC++を取り除きたいですか?優秀な図書館がすでに存在するときは、誰もあなた自身のbignum図書館を作成することを通してあなたを導くとは思わない(GMP)。 –
"スピードが必要であることを知っているので、C++で文字列の算術演算を行うクラスを作成することにしました。 あなたは、実際にあなたのパフォーマンスを(多くの場合、ベースとして可能な最大のタイプを取る)助けにならない文字列(つまり、文字のビルド)を話すときに私がやっていると思うと思います。それ以外にも、2 ^(2^31)の順番で番号が必要であることを正しく理解していますか?そのような場合は、本当にあなたが得ることができるすべてのスピードが必要なので、私はそのようなクラスを自分で書くことに反対します。 – Grizzly
答えがバイナリである場合は、計算を行う必要はありません(Oliの答えに記載されているように、1に続いて 'n-1'ゼロを書きます)。しかし、答えを10進数で表示したい場合は...まあ... JavaのBigIntegerを使って計算してはいけません。そして、あなたが 'n> 2^32'よりもかなり大きなサイズを話しているなら、 GMPを使ってGMPを計算すると、それが起こる前にメモリが足りなくなるでしょう... – Mysticial